diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2016-03-12 09:34:00 +0900 |
---|---|---|
committer | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2016-03-12 10:05:57 +0900 |
commit | 376d5b3bb8fa65ace77bc3423e16ee2078038058 (patch) | |
tree | 997e9601849991d89b933d191d5aacc78efc2f81 | |
parent | 79a8275508e252213c857151f27a93abae43f6a1 (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.go | 46 | ||||
-rw-r--r-- | server/sockopt_linux.go | 24 |
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), "") |