[PATCH] BGP: Add support for BGP hostname capability
Vincent Bernat
vincent at bernat.ch
Wed Feb 3 19:19:50 CET 2021
This is an implementation of draft-walton-bgp-hostname-capability-02.
It's implemented since quite some time for FRR and in datacenter, this
gives a nice output to avoid using IP addresses.
Currently, it is always enabled. The hostname is retrieved from
uname(2) and not configurable. The domain name is never set nor
displayed. I don't think being able to set the hostname is very
important. I don't think the domain name is useful. However, maybe the
capability should not be enabled by default.
Also, the case where the capability is supported but hostname is empty
is handled as if the capability was not supported. I think this is not
worth handling such an edge case. The RFC doesn't say if hostname is
optional or not.
The return code of uname(2) is not checked, but I think this is
not bound to happen and if it happens, this is handled nicely by
disabling the capability.
The draft is expired but I hope a second implementation could allow to
revive it.
Output from BIRD:
Local capabilities
Multiprotocol
AF announced: ipv6
Route refresh
Graceful restart
4-octet AS numbers
Enhanced refresh
Long-lived graceful restart
Hostname: bird2
Neighbor capabilities
Multiprotocol
AF announced: ipv6
Route refresh
Graceful restart
4-octet AS numbers
ADD-PATH
RX: ipv6
TX:
Hostname: frr1
Output from FRR:
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt
bird1(2001:db8::11) 4 65000 548 495 0 0 0 00:03:06 0 0
bird2(2001:db8::12) 4 65000 281 256 0 0 0 00:01:49 0 0
frr2(2001:db8::22) 4 65000 501 501 0 0 0 00:24:56 0 0
Signed-off-by: Vincent Bernat <vincent at bernat.ch>
---
proto/bgp/bgp.c | 3 +++
proto/bgp/bgp.h | 2 ++
proto/bgp/config.Y | 1 +
proto/bgp/packets.c | 38 ++++++++++++++++++++++++++++++++++++++
4 files changed, 44 insertions(+)
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 302d026c0103..d4c15f0538b1 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -2415,6 +2415,9 @@ bgp_show_capabilities(struct bgp_proto *p UNUSED, struct bgp_caps *caps)
bgp_show_afis(-1006, " AF supported:", afl1, afn1);
bgp_show_afis(-1006, " AF preserved:", afl2, afn2);
}
+
+ if (*caps->hostname)
+ cli_msg(-1006, " Hostname: %s", caps->hostname);
}
static void
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index dd7dc28fd03d..3a99bc9667b5 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -98,6 +98,7 @@ struct bgp_config {
int enable_refresh; /* Enable local support for route refresh [RFC 2918] */
int enable_as4; /* Enable local support for 4B AS numbers [RFC 6793] */
int enable_extended_messages; /* Enable local support for extended messages [draft] */
+ int enable_hostname; /* Enable local support for hostname [draft] */
u32 rr_cluster_id; /* Route reflector cluster ID, if different from local ID */
int rr_client; /* Whether neighbor is RR client of me */
int rs_client; /* Whether neighbor is RS client of me */
@@ -225,6 +226,7 @@ struct bgp_caps {
u16 gr_time; /* Graceful restart time in seconds */
u8 llgr_aware; /* Long-lived GR capability, RFC draft */
+ char hostname[UINT8_MAX + 1]; /* Hostname, RFC draft */
u8 any_ext_next_hop; /* Bitwise OR of per-AF ext_next_hop */
u8 any_add_path; /* Bitwise OR of per-AF add_path */
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index 18c3560dfc9b..f8bd4ef03b11 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -62,6 +62,7 @@ bgp_proto_start: proto_start BGP {
BGP_CFG->error_delay_time_max = 300;
BGP_CFG->enable_refresh = 1;
BGP_CFG->enable_as4 = 1;
+ BGP_CFG->enable_hostname = 1;
BGP_CFG->capabilities = 2;
BGP_CFG->interpret_communities = 1;
BGP_CFG->allow_as_sets = 1;
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index 78fdd1e006a3..71ab1be48b46 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -11,6 +11,7 @@
#undef LOCAL_DEBUG
#include <stdlib.h>
+#include <sys/utsname.h>
#include "nest/bird.h"
#include "nest/iface.h"
@@ -221,6 +222,8 @@ bgp_prepare_capabilities(struct bgp_conn *conn)
struct bgp_channel *c;
struct bgp_caps *caps;
struct bgp_af_caps *ac;
+ struct utsname uts = {};
+ size_t length;
if (!p->cf->capabilities)
{
@@ -252,6 +255,16 @@ bgp_prepare_capabilities(struct bgp_conn *conn)
if (p->cf->llgr_mode)
caps->llgr_aware = 1;
+ if (p->cf->enable_hostname)
+ {
+ uname(&uts);
+ if ((length = strlen(uts.nodename)) > UINT8_MAX)
+ length = UINT8_MAX;
+ memcpy(caps->hostname, uts.nodename, length);
+ caps->hostname[length] = 0;
+ }
+
+
/* Allocate and fill per-AF fields */
WALK_LIST(c, p->p.channels)
{
@@ -295,6 +308,7 @@ bgp_write_capabilities(struct bgp_conn *conn, byte *buf)
struct bgp_af_caps *ac;
byte *buf_head = buf;
byte *data;
+ size_t length;
/* Create capability list in buffer */
@@ -412,6 +426,24 @@ bgp_write_capabilities(struct bgp_conn *conn, byte *buf)
data[-1] = buf - data;
}
+ if (*caps->hostname)
+ {
+ *buf++ = 73; /* Capability 73: Hostname */
+ *buf++ = 0; /* Capability data length */
+ data = buf;
+
+ /* Hostname */
+ length = strlen(caps->hostname);
+ *buf++ = length;
+ memcpy(buf, caps->hostname, length);
+ buf += length;
+
+ /* Domain, not implemented */
+ *buf++ = 0;
+
+ data[-1] = buf - data;
+ }
+
caps->length = buf - buf_head;
return buf;
@@ -573,6 +605,12 @@ bgp_read_capabilities(struct bgp_conn *conn, byte *pos, int len)
}
break;
+ case 73: /* Hostname, RFC draft */
+ if (cl < 2 || cl < 2 + pos[2])
+ goto err;
+
+ memcpy(caps->hostname, pos + 3, pos[2]);
+
/* We can safely ignore all other capabilities */
}
--
2.30.0
More information about the Bird-users
mailing list