diff options
author | Hitoshi Irino <irino@sfc.wide.ad.jp> | 2019-06-24 00:39:22 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@gmail.com> | 2019-07-02 11:40:22 +0900 |
commit | 2f5a4d59cb8d494bcf1a64d45d84bcd8fd4a7f06 (patch) | |
tree | 130afc174fe85d32abe3ad4994aecec3461ffcc4 /pkg | |
parent | 9f936065a907639661eca3924f0a8f09d94abbfe (diff) |
BGP connection on a speecified interface (including which is associated VRF) using syscall SO_BINDTODEVICE
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/server/fsm.go | 6 | ||||
-rw-r--r-- | pkg/server/grpc_server.go | 1 | ||||
-rw-r--r-- | pkg/server/server.go | 4 | ||||
-rw-r--r-- | pkg/server/sockopt.go | 2 | ||||
-rw-r--r-- | pkg/server/sockopt_linux.go | 12 | ||||
-rw-r--r-- | pkg/server/sockopt_openbsd.go | 2 |
6 files changed, 20 insertions, 7 deletions
diff --git a/pkg/server/fsm.go b/pkg/server/fsm.go index ae102812..b06ddd5d 100644 --- a/pkg/server/fsm.go +++ b/pkg/server/fsm.go @@ -491,7 +491,7 @@ func (h *fsmHandler) connectLoop(ctx context.Context, wg *sync.WaitGroup) { defer wg.Done() fsm := h.fsm - retry, addr, port, password, ttl, ttlMin, localAddress := func() (int, string, int, string, uint8, uint8, string) { + retry, addr, port, password, ttl, ttlMin, localAddress, bindInterface := func() (int, string, int, string, uint8, uint8, string, string) { fsm.lock.RLock() defer fsm.lock.RUnlock() @@ -518,7 +518,7 @@ func (h *fsmHandler) connectLoop(ctx context.Context, wg *sync.WaitGroup) { ttl = fsm.pConf.EbgpMultihop.Config.MultihopTtl } } - return tick, addr, port, password, ttl, ttlMin, fsm.pConf.Transport.Config.LocalAddress + return tick, addr, port, password, ttl, ttlMin, fsm.pConf.Transport.Config.LocalAddress, fsm.pConf.Transport.Config.BindInterface }() tick := minConnectRetryInterval @@ -553,7 +553,7 @@ func (h *fsmHandler) connectLoop(ctx context.Context, wg *sync.WaitGroup) { LocalAddr: laddr, Timeout: time.Duration(tick-1) * time.Second, Control: func(network, address string, c syscall.RawConn) error { - return dialerControl(network, address, c, ttl, ttlMin, password) + return dialerControl(network, address, c, ttl, ttlMin, password, bindInterface) }, } diff --git a/pkg/server/grpc_server.go b/pkg/server/grpc_server.go index 0d6f7d9c..2540e685 100644 --- a/pkg/server/grpc_server.go +++ b/pkg/server/grpc_server.go @@ -655,6 +655,7 @@ func newNeighborFromAPIStruct(a *api.Peer) (*config.Neighbor, error) { pconf.Transport.Config.LocalAddress = a.Transport.LocalAddress pconf.Transport.Config.PassiveMode = a.Transport.PassiveMode pconf.Transport.Config.RemotePort = uint16(a.Transport.RemotePort) + pconf.Transport.Config.BindInterface = a.Transport.BindInterface } if a.EbgpMultihop != nil { pconf.EbgpMultihop.Config.Enabled = a.EbgpMultihop.Enabled diff --git a/pkg/server/server.go b/pkg/server/server.go index 82efeb6a..d77512f5 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -250,6 +250,7 @@ func (s *BgpServer) passConnToPeer(conn *net.TCPConn) { } peer.fsm.lock.RLock() localAddr := peer.fsm.pConf.Transport.Config.LocalAddress + bindInterface := peer.fsm.pConf.Transport.Config.BindInterface peer.fsm.lock.RUnlock() localAddrValid := func(laddr string) bool { if laddr == "0.0.0.0" || laddr == "::" { @@ -262,12 +263,13 @@ func (s *BgpServer) passConnToPeer(conn *net.TCPConn) { } host, _, _ := net.SplitHostPort(l.String()) - if host != laddr { + if host != laddr && bindInterface == "" { log.WithFields(log.Fields{ "Topic": "Peer", "Key": remoteAddr, "Configured addr": laddr, "Addr": host, + "BindInterface": bindInterface, }).Info("Mismatched local address") return false } diff --git a/pkg/server/sockopt.go b/pkg/server/sockopt.go index e2b1c086..0aab0ba9 100644 --- a/pkg/server/sockopt.go +++ b/pkg/server/sockopt.go @@ -39,7 +39,7 @@ func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error { return setTcpMinTTLSockopt(conn, ttl) } -func dialerControl(network, address string, c syscall.RawConn, ttl, ttlMin uint8, password string) error { +func dialerControl(network, address string, c syscall.RawConn, ttl, ttlMin uint8, password string, bindInterface string) error { if password != "" { log.WithFields(log.Fields{ "Topic": "Peer", diff --git a/pkg/server/sockopt_linux.go b/pkg/server/sockopt_linux.go index 31df8397..203087ab 100644 --- a/pkg/server/sockopt_linux.go +++ b/pkg/server/sockopt_linux.go @@ -103,7 +103,7 @@ func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error { return setsockOptInt(sc, level, name, ttl) } -func dialerControl(network, address string, c syscall.RawConn, ttl, minTtl uint8, password string) error { +func dialerControl(network, address string, c syscall.RawConn, ttl, minTtl uint8, password string, bindInterface string) error { family := syscall.AF_INET raddr, _ := net.ResolveTCPAddr("tcp", address) if raddr.IP.To4() == nil { @@ -161,5 +161,15 @@ func dialerControl(network, address string, c syscall.RawConn, ttl, minTtl uint8 return sockerr } } + if bindInterface != "" { + if err := c.Control(func(fd uintptr) { + sockerr = os.NewSyscallError("setsockopt", syscall.SetsockoptString(int(fd), syscall.SOL_SOCKET, syscall.SO_BINDTODEVICE, bindInterface)) + }); err != nil { + return err + } + if sockerr != nil { + return sockerr + } + } return nil } diff --git a/pkg/server/sockopt_openbsd.go b/pkg/server/sockopt_openbsd.go index e65aabe0..3d6825e2 100644 --- a/pkg/server/sockopt_openbsd.go +++ b/pkg/server/sockopt_openbsd.go @@ -403,7 +403,7 @@ func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error { return setsockOptInt(sc, level, name, ttl) } -func dialerControl(network, address string, c syscall.RawConn, ttl, minTtl uint8, password string) error { +func dialerControl(network, address string, c syscall.RawConn, ttl, minTtl uint8, password string, bindInterface string) error { if password != "" { log.WithFields(log.Fields{ "Topic": "Peer", |