diff options
author | Donatas Abraitis <donatas.abraitis@gmail.com> | 2021-05-24 09:55:03 +0300 |
---|---|---|
committer | Donatas Abraitis <donatas.abraitis@gmail.com> | 2021-05-24 09:55:03 +0300 |
commit | 94d720ff40644d09d99829d6a1520075b9f8475a (patch) | |
tree | 4fc816ce7ad55a140e81aec21018e1bd38ce5d9a /pkg/packet/bgp/bgp.go | |
parent | cbdb752b10847163d9f942853b67cf173b6aa151 (diff) |
Add FQDN capability
It's not kinda RFC (draft), but it's implemented and used in various
other open-source software like FRRouting, Bird, ExaBGP.
It's very handy when dealing with lots of peers.
Exampe between GoBGP and FRRouting:
```
% ./cmd/gobgp/gobgp neighbor 192.168.10.123 | grep -A4 fqdn:
fqdn: advertised and received
Local:
name: donatas-pc, domain:
Remote:
name: exit1-debian-9, domain:
```
```
% vtysh -c 'show bgp neighbors 192.168.10.17 json' | jq .'"192.168.10.17".neighborCapabilities.hostName'
{
"advHostName": "exit1-debian-9",
"advDomainName": "n/a",
"rcvHostName": "donatas-pc",
"rcvDomainName": "n/a"
}
```
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
Diffstat (limited to 'pkg/packet/bgp/bgp.go')
-rw-r--r-- | pkg/packet/bgp/bgp.go | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/pkg/packet/bgp/bgp.go b/pkg/packet/bgp/bgp.go index 15e15362..5403a5f3 100644 --- a/pkg/packet/bgp/bgp.go +++ b/pkg/packet/bgp/bgp.go @@ -295,6 +295,7 @@ const ( BGP_CAP_ADD_PATH BGPCapabilityCode = 69 BGP_CAP_ENHANCED_ROUTE_REFRESH BGPCapabilityCode = 70 BGP_CAP_LONG_LIVED_GRACEFUL_RESTART BGPCapabilityCode = 71 + BGP_CAP_FQDN BGPCapabilityCode = 73 BGP_CAP_ROUTE_REFRESH_CISCO BGPCapabilityCode = 128 ) @@ -309,6 +310,7 @@ var CapNameMap = map[BGPCapabilityCode]string{ BGP_CAP_ENHANCED_ROUTE_REFRESH: "enhanced-route-refresh", BGP_CAP_ROUTE_REFRESH_CISCO: "cisco-route-refresh", BGP_CAP_LONG_LIVED_GRACEFUL_RESTART: "long-lived-graceful-restart", + BGP_CAP_FQDN: "fqdn", } func (c BGPCapabilityCode) String() string { @@ -916,6 +918,71 @@ func NewCapLongLivedGracefulRestart(tuples []*CapLongLivedGracefulRestartTuple) } } +type CapFQDN struct { + DefaultParameterCapability + HostNameLen uint8 + HostName string + DomainNameLen uint8 + DomainName string +} + +func (c *CapFQDN) DecodeFromBytes(data []byte) error { + c.DefaultParameterCapability.DecodeFromBytes(data) + data = data[2:] + if len(data) < 2 { + return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_CAPABILITY, nil, "Not all CapabilityFQDN bytes allowed") + } + hostNameLen := uint8(data[0]) + c.HostNameLen = hostNameLen + c.HostName = string(data[1 : c.HostNameLen+1]) + domainNameLen := uint8(data[c.HostNameLen+1]) + c.DomainNameLen = domainNameLen + c.DomainName = string(data[c.HostNameLen+2:]) + return nil +} + +func (c *CapFQDN) Serialize() ([]byte, error) { + buf := make([]byte, c.HostNameLen+c.DomainNameLen+2) + buf[0] = c.HostNameLen + copy(buf[1:c.HostNameLen+1], c.HostName) + buf[c.HostNameLen+1] = c.DomainNameLen + copy(buf[c.HostNameLen+2:], c.DomainName) + c.DefaultParameterCapability.CapValue = buf + return c.DefaultParameterCapability.Serialize() +} + +func (c *CapFQDN) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + HostNameLen uint8 `json:"hostname_len"` + HostName string `json:"hostname"` + DomainNameLen uint8 `json:"domainname_len"` + DomainName string `json:"domainname"` + }{ + HostNameLen: c.HostNameLen, + HostName: c.HostName, + DomainNameLen: c.DomainNameLen, + DomainName: c.DomainName, + }) +} + +func NewCapFQDN(hostname string, domainname string) *CapFQDN { + if len(hostname) > 64 { + hostname = hostname[:64] + } + if len(domainname) > 64 { + domainname = domainname[:64] + } + return &CapFQDN{ + DefaultParameterCapability{ + CapCode: BGP_CAP_FQDN, + }, + uint8(len(hostname)), + hostname, + uint8(len(domainname)), + domainname, + } +} + type CapUnknown struct { DefaultParameterCapability } @@ -955,6 +1022,8 @@ func DecodeCapability(data []byte) (ParameterCapabilityInterface, error) { c = &CapRouteRefreshCisco{} case BGP_CAP_LONG_LIVED_GRACEFUL_RESTART: c = &CapLongLivedGracefulRestart{} + case BGP_CAP_FQDN: + c = &CapFQDN{} default: c = &CapUnknown{} } |