Skip to content
Snippets Groups Projects
Unverified Commit f2a77ce0 authored by Annika Wickert's avatar Annika Wickert Committed by GitHub
Browse files

Merge pull request #251 from bio-routing/bgp/ttl

Add support for setting TTL on BGP sessions
parents d25d3e28 35847dfd
No related branches found
No related tags found
No related merge requests found
...@@ -28,6 +28,7 @@ type BGPGroup struct { ...@@ -28,6 +28,7 @@ type BGPGroup struct {
Name string `yaml:"name"` Name string `yaml:"name"`
LocalAddress string `yaml:"local_address"` LocalAddress string `yaml:"local_address"`
LocalAddressIP *bnet.IP LocalAddressIP *bnet.IP
TTL uint8 `yaml:"ttl"`
AuthenticationKey string `yaml:"authentication_key"` AuthenticationKey string `yaml:"authentication_key"`
PeerAS uint32 `yaml:"peer_as"` PeerAS uint32 `yaml:"peer_as"`
LocalAS uint32 `yaml:"local_as"` LocalAS uint32 `yaml:"local_as"`
...@@ -72,6 +73,10 @@ func (bg *BGPGroup) load(localAS uint32, policyOptions *PolicyOptions) error { ...@@ -72,6 +73,10 @@ func (bg *BGPGroup) load(localAS uint32, policyOptions *PolicyOptions) error {
n.LocalAddress = bg.LocalAddress n.LocalAddress = bg.LocalAddress
} }
if n.TTL == 0 {
n.TTL = bg.TTL
}
if n.AuthenticationKey == "" { if n.AuthenticationKey == "" {
n.AuthenticationKey = bg.AuthenticationKey n.AuthenticationKey = bg.AuthenticationKey
} }
...@@ -115,6 +120,7 @@ type BGPNeighbor struct { ...@@ -115,6 +120,7 @@ type BGPNeighbor struct {
PeerAddressIP *bnet.IP PeerAddressIP *bnet.IP
LocalAddress string `yaml:"local_address"` LocalAddress string `yaml:"local_address"`
LocalAddressIP *bnet.IP LocalAddressIP *bnet.IP
TTL uint8 `yaml:"ttl"`
AuthenticationKey string `yaml:"authentication_key"` AuthenticationKey string `yaml:"authentication_key"`
PeerAS uint32 `yaml:"peer_as"` PeerAS uint32 `yaml:"peer_as"`
LocalAS uint32 `yaml:"local_as"` LocalAS uint32 `yaml:"local_as"`
......
...@@ -189,6 +189,7 @@ func BGPPeerConfig(n *config.BGPNeighbor, vrf *vrf.VRF) *bgpserver.PeerConfig { ...@@ -189,6 +189,7 @@ func BGPPeerConfig(n *config.BGPNeighbor, vrf *vrf.VRF) *bgpserver.PeerConfig {
PeerAS: n.PeerAS, PeerAS: n.PeerAS,
PeerAddress: n.PeerAddressIP, PeerAddress: n.PeerAddressIP,
LocalAddress: n.LocalAddressIP, LocalAddress: n.LocalAddressIP,
TTL: n.TTL,
ReconnectInterval: time.Second * 15, ReconnectInterval: time.Second * 15,
HoldTime: n.HoldTimeDuration, HoldTime: n.HoldTimeDuration,
KeepAlive: n.HoldTimeDuration / 3, KeepAlive: n.HoldTimeDuration / 3,
......
...@@ -54,6 +54,12 @@ func (s *activeState) connectRetryTimerExpired() (state, string) { ...@@ -54,6 +54,12 @@ func (s *activeState) connectRetryTimerExpired() (state, string) {
} }
func (s *activeState) connectionSuccess(con net.Conn) (state, string) { func (s *activeState) connectionSuccess(con net.Conn) (state, string) {
if s.fsm.peer.ttl != 0 {
SetTCPConnTTLSockopt(con, s.fsm.peer.ttl)
} else if s.fsm.peer.isEBGP() {
SetTCPConnTTLSockopt(con, 1)
}
s.fsm.con = con s.fsm.con = con
stopTimer(s.fsm.connectRetryTimer) stopTimer(s.fsm.connectRetryTimer)
err := s.fsm.sendOpen() err := s.fsm.sendOpen()
......
...@@ -37,6 +37,12 @@ func (s connectState) run() (state, string) { ...@@ -37,6 +37,12 @@ func (s connectState) run() (state, string) {
} }
func (s *connectState) connectionSuccess(c net.Conn) (state, string) { func (s *connectState) connectionSuccess(c net.Conn) (state, string) {
if s.fsm.peer.ttl != 0 {
SetTCPConnTTLSockopt(c, s.fsm.peer.ttl)
} else if s.fsm.peer.isEBGP() {
SetTCPConnTTLSockopt(c, 1)
}
s.fsm.con = c s.fsm.con = c
stopTimer(s.fsm.connectRetryTimer) stopTimer(s.fsm.connectRetryTimer)
err := s.fsm.sendOpen() err := s.fsm.sendOpen()
......
...@@ -20,6 +20,7 @@ type peer struct { ...@@ -20,6 +20,7 @@ type peer struct {
config *PeerConfig config *PeerConfig
addr *bnet.IP addr *bnet.IP
localAddr *bnet.IP localAddr *bnet.IP
ttl uint8
passive bool passive bool
peerASN uint32 peerASN uint32
localASN uint32 localASN uint32
...@@ -51,6 +52,7 @@ type PeerConfig struct { ...@@ -51,6 +52,7 @@ type PeerConfig struct {
HoldTime time.Duration HoldTime time.Duration
LocalAddress *bnet.IP LocalAddress *bnet.IP
PeerAddress *bnet.IP PeerAddress *bnet.IP
TTL uint8
LocalAS uint32 LocalAS uint32
PeerAS uint32 PeerAS uint32
Passive bool Passive bool
...@@ -242,6 +244,7 @@ func newPeer(c PeerConfig, server *bgpServer) (*peer, error) { ...@@ -242,6 +244,7 @@ func newPeer(c PeerConfig, server *bgpServer) (*peer, error) {
server: server, server: server,
config: &c, config: &c,
addr: c.PeerAddress, addr: c.PeerAddress,
ttl: c.TTL,
passive: c.Passive, passive: c.Passive,
peerASN: c.PeerAS, peerASN: c.PeerAS,
localASN: c.LocalAS, localASN: c.LocalAS,
...@@ -401,3 +404,7 @@ func (p *peer) stop() { ...@@ -401,3 +404,7 @@ func (p *peer) stop() {
fsm.eventCh <- ManualStop fsm.eventCh <- ManualStop
} }
} }
func (p *peer) isEBGP() bool {
return p.localASN != p.peerASN
}
...@@ -11,7 +11,8 @@ const ( ...@@ -11,7 +11,8 @@ const (
IPV6_MINHOPCOUNT = 73 // Generalized TTL Security Mechanism (RFC5082) IPV6_MINHOPCOUNT = 73 // Generalized TTL Security Mechanism (RFC5082)
) )
func SetListenTCPTTLSockopt(l *net.TCPListener, ttl int) error { // SetListenTCPTTLSockopt sets the TTL on a TCP listener
func SetListenTCPTTLSockopt(l *net.TCPListener, ttl uint8) error {
fi, family, err := extractFileAndFamilyFromTCPListener(l) fi, family, err := extractFileAndFamilyFromTCPListener(l)
defer fi.Close() defer fi.Close()
if err != nil { if err != nil {
...@@ -20,12 +21,30 @@ func SetListenTCPTTLSockopt(l *net.TCPListener, ttl int) error { ...@@ -20,12 +21,30 @@ func SetListenTCPTTLSockopt(l *net.TCPListener, ttl int) error {
return setsockoptIPTTL(int(fi.Fd()), family, ttl) return setsockoptIPTTL(int(fi.Fd()), family, ttl)
} }
func setsockoptIPTTL(fd int, family int, value int) error { // SetTCPConnTTLSockopt sets the TTL on a TCP connection
func SetTCPConnTTLSockopt(c net.Conn, ttl uint8) error {
switch c.(type) {
case *net.TCPConn:
default:
return nil
}
fi, family, err := extractFileAndFamilyFromTCPConn(c.(*net.TCPConn))
defer fi.Close()
if err != nil {
return err
}
return setsockoptIPTTL(int(fi.Fd()), family, ttl)
}
func setsockoptIPTTL(fd int, family int, value uint8) error {
level := syscall.IPPROTO_IP level := syscall.IPPROTO_IP
name := syscall.IP_TTL name := syscall.IP_TTL
if family == syscall.AF_INET6 { if family == syscall.AF_INET6 {
level = syscall.IPPROTO_IPV6 level = syscall.IPPROTO_IPV6
name = syscall.IPV6_UNICAST_HOPS name = syscall.IPV6_UNICAST_HOPS
} }
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, level, name, value))
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, level, name, int(value)))
} }
...@@ -24,10 +24,33 @@ func extractFileAndFamilyFromTCPListener(l *net.TCPListener) (*os.File, int, err ...@@ -24,10 +24,33 @@ func extractFileAndFamilyFromTCPListener(l *net.TCPListener) (*os.File, int, err
} }
fl.Close() fl.Close()
family := syscall.AF_INET return fi, getAFIFromAddr(l.Addr().String()), nil
if strings.Contains(l.Addr().String(), "[") { }
family = syscall.AF_INET6
func extractFileAndFamilyFromTCPConn(c *net.TCPConn) (*os.File, int, error) {
// Note #1: TCPListener.File() has the unexpected side-effect of putting
// the original socket into blocking mode. See Note #2.
fi, err := c.File()
if err != nil {
return nil, 0, err
}
// Note #2: Call net.FileListener() to put the original socket back into
// non-blocking mode.
fl, err := net.FileListener(fi)
if err != nil {
fi.Close()
return nil, 0, err
}
fl.Close()
return fi, getAFIFromAddr(c.LocalAddr().String()), nil
}
func getAFIFromAddr(addr string) int {
if strings.Contains(addr, "[") {
return syscall.AF_INET6
} }
return fi, family, nil return syscall.AF_INET
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment