diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/server/server.go | 52 | ||||
-rw-r--r-- | pkg/server/sockopt.go | 9 | ||||
-rw-r--r-- | pkg/server/sockopt_bsd.go | 9 | ||||
-rw-r--r-- | pkg/server/sockopt_darwin.go | 9 | ||||
-rw-r--r-- | pkg/server/sockopt_linux.go | 16 | ||||
-rw-r--r-- | pkg/server/sockopt_openbsd.go | 13 | ||||
-rw-r--r-- | pkg/server/util.go | 8 |
7 files changed, 49 insertions, 67 deletions
diff --git a/pkg/server/server.go b/pkg/server/server.go index d9a65c0f..c5b2b0ff 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -23,6 +23,7 @@ import ( "reflect" "strconv" "sync" + "syscall" "time" "github.com/eapache/channels" @@ -52,35 +53,56 @@ func (l *tcpListener) Close() error { } // avoid mapped IPv6 address -func newTCPListener(address string, port uint32, ch chan *net.TCPConn) (*tcpListener, error) { +func newTCPListener(address string, port uint32, bindToDev string, ch chan *net.TCPConn) (*tcpListener, error) { proto := "tcp4" + family := syscall.AF_INET if ip := net.ParseIP(address); ip == nil { return nil, fmt.Errorf("can't listen on %s", address) } else if ip.To4() == nil { proto = "tcp6" + family = syscall.AF_INET6 } - addr, err := net.ResolveTCPAddr(proto, net.JoinHostPort(address, strconv.Itoa(int(port)))) - if err != nil { - return nil, err + addr := net.JoinHostPort(address, strconv.Itoa(int(port))) + + var lc net.ListenConfig + lc.Control = func(network, address string, c syscall.RawConn) error { + if bindToDev != "" { + err := setBindToDevSockopt(c, bindToDev) + if err != nil { + log.WithFields(log.Fields{ + "Topic": "Peer", + "Key": addr, + "BindToDev": bindToDev, + }).Warnf("failed to bind Listener to device (%s): %s", bindToDev, err) + return err + } + } + // Note: Set TTL=255 for incoming connection listener in order to accept + // connection in case for the neighbor has TTL Security settings. + err := setsockoptIpTtl(c, family, 255) + if err != nil { + log.WithFields(log.Fields{ + "Topic": "Peer", + "Key": addr, + }).Warnf("cannot set TTL(=%d) for TCPListener: %s", 255, err) + } + return nil } - l, err := net.ListenTCP(proto, addr) + l, err := lc.Listen(context.Background(), proto, addr) if err != nil { return nil, err } - // Note: Set TTL=255 for incoming connection listener in order to accept - // connection in case for the neighbor has TTL Security settings. - if err := setListenTCPTTLSockopt(l, 255); err != nil { - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": addr, - }).Warnf("cannot set TTL(=%d) for TCPListener: %s", 255, err) + listener, ok := l.(*net.TCPListener) + if !ok { + err = fmt.Errorf("unexpected connection listener (not for TCP)") + return nil, err } closeCh := make(chan struct{}) go func() error { for { - conn, err := l.AcceptTCP() + conn, err := listener.AcceptTCP() if err != nil { close(closeCh) log.WithFields(log.Fields{ @@ -93,7 +115,7 @@ func newTCPListener(address string, port uint32, ch chan *net.TCPConn) (*tcpList } }() return &tcpListener{ - l: l, + l: listener, ch: closeCh, }, nil } @@ -2101,7 +2123,7 @@ func (s *BgpServer) StartBgp(ctx context.Context, r *api.StartBgpRequest) error if c.Config.Port > 0 { acceptCh := make(chan *net.TCPConn, 4096) for _, addr := range c.Config.LocalAddressList { - l, err := newTCPListener(addr, uint32(c.Config.Port), acceptCh) + l, err := newTCPListener(addr, uint32(c.Config.Port), g.BindToDevice, acceptCh) if err != nil { return err } diff --git a/pkg/server/sockopt.go b/pkg/server/sockopt.go index 0aab0ba9..235bbbb9 100644 --- a/pkg/server/sockopt.go +++ b/pkg/server/sockopt.go @@ -17,6 +17,7 @@ package server import ( + "fmt" "net" "syscall" @@ -27,10 +28,6 @@ func setTCPMD5SigSockopt(l *net.TCPListener, address string, key string) error { return setTcpMD5SigSockopt(l, address, key) } -func setListenTCPTTLSockopt(l *net.TCPListener, ttl int) error { - return setListenTcpTTLSockopt(l, ttl) -} - func setTCPTTLSockopt(conn *net.TCPConn, ttl int) error { return setTcpTTLSockopt(conn, ttl) } @@ -39,6 +36,10 @@ func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error { return setTcpMinTTLSockopt(conn, ttl) } +func setBindToDevSockopt(sc syscall.RawConn, device string) error { + return fmt.Errorf("binding connection to a device is not supported") +} + func dialerControl(network, address string, c syscall.RawConn, ttl, ttlMin uint8, password string, bindInterface string) error { if password != "" { log.WithFields(log.Fields{ diff --git a/pkg/server/sockopt_bsd.go b/pkg/server/sockopt_bsd.go index fe7a6134..942e1289 100644 --- a/pkg/server/sockopt_bsd.go +++ b/pkg/server/sockopt_bsd.go @@ -35,15 +35,6 @@ func setTcpMD5SigSockopt(l *net.TCPListener, address string, key string) error { return setsockOptInt(sc, syscall.IPPROTO_TCP, tcpMD5SIG, 1) } -func setListenTcpTTLSockopt(l *net.TCPListener, ttl int) error { - family := extractFamilyFromTCPListener(l) - sc, err := l.SyscallConn() - if err != nil { - return err - } - return setsockoptIpTtl(sc, family, ttl) -} - func setTcpTTLSockopt(conn *net.TCPConn, ttl int) error { family := extractFamilyFromTCPConn(conn) sc, err := conn.SyscallConn() diff --git a/pkg/server/sockopt_darwin.go b/pkg/server/sockopt_darwin.go index abb69d35..30220952 100644 --- a/pkg/server/sockopt_darwin.go +++ b/pkg/server/sockopt_darwin.go @@ -27,15 +27,6 @@ func setTcpMD5SigSockopt(l *net.TCPListener, address string, key string) error { return fmt.Errorf("setting md5 is not supported") } -func setListenTcpTTLSockopt(l *net.TCPListener, ttl int) error { - family := extractFamilyFromTCPListener(l) - sc, err := l.SyscallConn() - if err != nil { - return err - } - return setsockoptIpTtl(sc, family, ttl) -} - func setTcpTTLSockopt(conn *net.TCPConn, ttl int) error { family := syscall.AF_INET if strings.Contains(conn.RemoteAddr().String(), "[") { diff --git a/pkg/server/sockopt_linux.go b/pkg/server/sockopt_linux.go index 203087ab..55d27bd4 100644 --- a/pkg/server/sockopt_linux.go +++ b/pkg/server/sockopt_linux.go @@ -70,13 +70,8 @@ func setTCPMD5SigSockopt(l *net.TCPListener, address string, key string) error { return setsockOptString(sc, syscall.IPPROTO_TCP, tcpMD5SIG, string(b[:])) } -func setListenTCPTTLSockopt(l *net.TCPListener, ttl int) error { - family := extractFamilyFromTCPListener(l) - sc, err := l.SyscallConn() - if err != nil { - return err - } - return setsockoptIpTtl(sc, family, ttl) +func setBindToDevSockopt(sc syscall.RawConn, device string) error { + return setsockOptString(sc, syscall.SOL_SOCKET, syscall.SO_BINDTODEVICE, device) } func setTCPTTLSockopt(conn *net.TCPConn, ttl int) error { @@ -162,14 +157,9 @@ func dialerControl(network, address string, c syscall.RawConn, ttl, minTtl uint8 } } 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 { + if err := setBindToDevSockopt(c, 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 3d6825e2..612047ca 100644 --- a/pkg/server/sockopt_openbsd.go +++ b/pkg/server/sockopt_openbsd.go @@ -370,15 +370,6 @@ func setTCPMD5SigSockopt(l *net.TCPListener, address string, key string) error { return setsockoptTcpMD5Sig(sc, address, key) } -func setListenTCPTTLSockopt(l *net.TCPListener, ttl int) error { - family := extractFamilyFromTCPListener(l) - sc, err := l.SyscallConn() - if err != nil { - return err - } - return setsockoptIpTtl(sc, family, ttl) -} - func setTCPTTLSockopt(conn *net.TCPConn, ttl int) error { family := extractFamilyFromTCPConn(conn) sc, err := conn.SyscallConn() @@ -403,6 +394,10 @@ func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error { return setsockOptInt(sc, level, name, ttl) } +func setBindToDevSockopt(sc syscall.RawConn, device string) error { + return fmt.Errorf("binding connection to a device is not supported") +} + func dialerControl(network, address string, c syscall.RawConn, ttl, minTtl uint8, password string, bindInterface string) error { if password != "" { log.WithFields(log.Fields{ diff --git a/pkg/server/util.go b/pkg/server/util.go index c774c6dd..e4abbed0 100644 --- a/pkg/server/util.go +++ b/pkg/server/util.go @@ -65,14 +65,6 @@ func decodeAdministrativeCommunication(data []byte) (string, []byte) { return string(data[1 : communicationLen+1]), data[communicationLen+1:] } -func extractFamilyFromTCPListener(l *net.TCPListener) int { - family := syscall.AF_INET - if strings.Contains(l.Addr().String(), "[") { - family = syscall.AF_INET6 - } - return family -} - func extractFamilyFromTCPConn(conn *net.TCPConn) int { family := syscall.AF_INET if strings.Contains(conn.RemoteAddr().String(), "[") { |