summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>2016-03-12 09:34:00 +0900
committerISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>2016-03-12 10:05:57 +0900
commit376d5b3bb8fa65ace77bc3423e16ee2078038058 (patch)
tree997e9601849991d89b933d191d5aacc78efc2f81
parent79a8275508e252213c857151f27a93abae43f6a1 (diff)
fsm: support active connection with md5 and binding
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
-rw-r--r--server/fsm.go46
-rw-r--r--server/sockopt_linux.go24
2 files changed, 44 insertions, 26 deletions
diff --git a/server/fsm.go b/server/fsm.go
index 94ee588e..168a0387 100644
--- a/server/fsm.go
+++ b/server/fsm.go
@@ -293,43 +293,41 @@ func (fsm *FSM) connectLoop() error {
host := net.JoinHostPort(addr, strconv.Itoa(bgp.BGP_PORT))
// check if LocalAddress has been configured
laddr := fsm.pConf.Transport.Config.LocalAddress
+ var conn net.Conn
+ var err error
if laddr != "" {
- lhost := net.JoinHostPort(laddr, "0")
- ltcpaddr, err := net.ResolveTCPAddr("tcp", lhost)
- if err != nil {
- log.WithFields(log.Fields{
- "Topic": "Peer",
- "Key": fsm.pConf.Config.NeighborAddress,
- }).Warnf("failed to resolve ltcpaddr: %s", err)
+ if fsm.pConf.Config.AuthPassword != "" {
+ deadline := (MIN_CONNECT_RETRY - 1) * 1000 // msec
+ conn, err = DialTCPTimeoutWithMD5Sig(addr, bgp.BGP_PORT, laddr, fsm.pConf.Config.AuthPassword, deadline)
} else {
- d := net.Dialer{LocalAddr: ltcpaddr, Timeout: time.Duration(MIN_CONNECT_RETRY-1) * time.Second}
- if conn, err := d.Dial("tcp", host); err == nil {
- fsm.connCh <- conn
- } else {
+ lhost := net.JoinHostPort(laddr, "0")
+ ltcpaddr, e := net.ResolveTCPAddr("tcp", lhost)
+ if e != nil {
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": fsm.pConf.Config.NeighborAddress,
- }).Debugf("failed to connect from ltcpaddr", err)
+ }).Warnf("failed to resolve ltcpaddr: %s", e)
+ return
}
+ d := net.Dialer{LocalAddr: ltcpaddr, Timeout: time.Duration(MIN_CONNECT_RETRY-1) * time.Second}
+ conn, err = d.Dial("tcp", host)
}
-
} else {
- var conn net.Conn
- var err error
if fsm.pConf.Config.AuthPassword != "" {
deadline := (MIN_CONNECT_RETRY - 1) * 1000 // msec
- conn, err = DialTCPTimeoutWithMD5Sig(addr, bgp.BGP_PORT, fsm.pConf.Config.AuthPassword, deadline)
+ conn, err = DialTCPTimeoutWithMD5Sig(addr, bgp.BGP_PORT, "0.0.0.0", fsm.pConf.Config.AuthPassword, deadline)
} else {
conn, err = net.DialTimeout("tcp", host, time.Duration(MIN_CONNECT_RETRY-1)*time.Second)
}
- if err == nil {
- fsm.connCh <- conn
- } else {
- log.WithFields(log.Fields{
- "Topic": "Peer",
- "Key": fsm.pConf.Config.NeighborAddress,
- }).Debugf("failed to connect: %s", err)
- }
+ }
+
+ if err == nil {
+ fsm.connCh <- conn
+ } else {
+ log.WithFields(log.Fields{
+ "Topic": "Peer",
+ "Key": fsm.pConf.Config.NeighborAddress,
+ }).Debugf("failed to connect: %s", err)
}
}
}
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), "")