diff options
author | Daniel Walton <dwalton@cumulusnetworks.com> | 2015-09-11 05:10:16 +0200 |
---|---|---|
committer | Daniel Walton <dwalton@cumulusnetworks.com> | 2015-09-11 05:10:16 +0200 |
commit | 04b6bdc0ee6275442464edec1d14b3f4d3eaa246 (patch) | |
tree | 402996c2ef60c5a4ed2f03a0a8e63d3ec7c8c154 /bgpd/bgp_open.c | |
parent | Fix arm compilation failures of sockunion_hash issues (diff) | |
download | frr-04b6bdc0ee6275442464edec1d14b3f4d3eaa246.tar.xz frr-04b6bdc0ee6275442464edec1d14b3f4d3eaa246.zip |
bgpd: Exchange hostname capability and display hostnames in output
This patch adds a hostname capability. The node's hostname and
domainname are exchanged in the new capability and used in show command
outputs based on a knob enabled by the user. The hostname and domainname
can be a maximum of 64 chars long, each.
Signed-off-by: Dinesh G Dutt <ddutt@cumulusnetworks.com>
Reviewed-by: Daniel Walton <dwalton@cumulusnetworks.com>
Reviewed-by: Vivek Venkataraman <vivek@cumulusnetworks.com>
Ticket: CM-5660
Reviewed By: CCR-2563
Testing Done:
Diffstat (limited to 'bgpd/bgp_open.c')
-rw-r--r-- | bgpd/bgp_open.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index a530542a4..3ab782b02 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -588,6 +588,85 @@ bgp_capability_enhe (struct peer *peer, struct capability_header *hdr) return 0; } +static int +bgp_capability_hostname (struct peer *peer, struct capability_header *hdr) +{ + struct stream *s = BGP_INPUT (peer); + char str[BGP_MAX_HOSTNAME+1]; + size_t end = stream_get_getp (s) + hdr->length; + u_char len; + + SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_RCV); + + len = stream_getc(s); + if (stream_get_getp(s) + len > end) + { + zlog_warn("%s: Received malformed hostname capability from peer %s", + __FUNCTION__, peer->host); + return -1; + } + + if (len > BGP_MAX_HOSTNAME) + { + stream_get(str, s, BGP_MAX_HOSTNAME); + stream_forward_getp(s, len-BGP_MAX_HOSTNAME); + len = BGP_MAX_HOSTNAME; /* to set the '\0' below */ + } + else if (len) + stream_get(str, s, len); + + if (len) + { + str[len] = '\0'; + + if (peer->hostname != NULL) + XFREE(MTYPE_HOST, peer->hostname); + + if (peer->domainname != NULL) + XFREE(MTYPE_HOST, peer->domainname); + + peer->hostname = XSTRDUP(MTYPE_HOST, str); + } + + if (stream_get_getp(s) +1 > end) + { + zlog_warn("%s: Received invalid domain name len (hostname capability) from peer %s", + __FUNCTION__, peer->host); + return -1; + } + + len = stream_getc(s); + if (stream_get_getp(s) + len > end) + { + zlog_warn("%s: Received runt domain name (hostname capability) from peer %s", + __FUNCTION__, peer->host); + return -1; + } + + if (len > BGP_MAX_HOSTNAME) + { + stream_get(str, s, BGP_MAX_HOSTNAME); + stream_forward_getp(s, len-BGP_MAX_HOSTNAME); + len = BGP_MAX_HOSTNAME; /* to set the '\0' below */ + } + else if (len) + stream_get(str, s, len); + + if (len) + { + str[len] = '\0'; + peer->domainname = XSTRDUP(MTYPE_HOST, str); + } + + if (bgp_debug_neighbor_events(peer)) + { + zlog_debug("%s received hostname %s, domainname %s", + peer->host, peer->hostname, peer->domainname); + } + + return 0; +} + static const struct message capcode_str[] = { { CAPABILITY_CODE_MP, "MultiProtocol Extensions" }, @@ -601,6 +680,7 @@ bgp_capability_enhe (struct peer *peer, struct capability_header *hdr) { CAPABILITY_CODE_DYNAMIC_OLD, "Dynamic (Old)" }, { CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)" }, { CAPABILITY_CODE_ORF_OLD, "ORF (Old)" }, + { CAPABILITY_CODE_FQDN, "FQDN" }, }; static const int capcode_str_max = array_size(capcode_str); @@ -618,6 +698,7 @@ static const size_t cap_minsizes[] = [CAPABILITY_CODE_ENHE] = CAPABILITY_CODE_ENHE_LEN, [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN, [CAPABILITY_CODE_ORF_OLD] = sizeof (struct capability_orf_entry), + [CAPABILITY_CODE_FQDN] = CAPABILITY_CODE_MIN_FQDN_LEN, }; /** @@ -684,6 +765,7 @@ bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability, case CAPABILITY_CODE_DYNAMIC: case CAPABILITY_CODE_DYNAMIC_OLD: case CAPABILITY_CODE_ENHE: + case CAPABILITY_CODE_FQDN: /* Check length. */ if (caphdr.length < cap_minsizes[caphdr.code]) { @@ -759,6 +841,9 @@ bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability, case CAPABILITY_CODE_ENHE: ret = bgp_capability_enhe (peer, &caphdr); break; + case CAPABILITY_CODE_FQDN: + ret = bgp_capability_hostname (peer, &caphdr); + break; default: if (caphdr.code > 128) { @@ -1099,6 +1184,7 @@ bgp_open_capability (struct stream *s, struct peer *peer) as_t local_as; u_int32_t restart_time; u_char afi_safi_count = 0; + struct utsname names; /* Remember current pointer for Opt Parm Len. */ cp = stream_get_endp (s); @@ -1265,6 +1351,51 @@ bgp_open_capability (struct stream *s, struct peer *peer) stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN); } + /* Hostname capability */ + uname(&names); + if (names.nodename[0] != '\0') + { + SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV); + stream_putc (s, BGP_OPEN_OPT_CAP); + rcapp = stream_get_endp(s); /* Ptr to length placeholder */ + stream_putc(s, 0); /* dummy len for now */ + stream_putc (s, CAPABILITY_CODE_FQDN); + capp = stream_get_endp(s); + stream_putc(s, 0); /* dummy len for now */ + len = strlen(names.nodename); + if (len > BGP_MAX_HOSTNAME) + len = BGP_MAX_HOSTNAME; + + stream_putc(s, len); + stream_put(s, names.nodename, len); +#ifdef _GNU_SOURCE + if ((names.domainname[0] != '\0') && + (strcmp(names.domainname, "(none)") != 0)) + { + len = strlen(names.domainname); + if (len > BGP_MAX_HOSTNAME) + len = BGP_MAX_HOSTNAME; + + stream_putc(s, len); + stream_put(s, names.domainname, len); + } + else +#endif + { + stream_putc(s, 0); /* 0 length */ + } + + /* Set the lengths straight */ + len = stream_get_endp(s) - rcapp - 1; + stream_putc_at(s, rcapp, len); + len = stream_get_endp(s) - capp - 1; + stream_putc_at(s, capp, len); + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s Sending hostname cap with hn = %s, dn = %s", + peer->host, names.nodename, names.domainname); + } + /* Sending base graceful-restart capability irrespective of the config */ SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV); stream_putc (s, BGP_OPEN_OPT_CAP); |