diff options
author | Donald Sharp <sharpd@cumulusnetworks.com> | 2015-05-20 03:29:16 +0200 |
---|---|---|
committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2015-05-20 03:29:16 +0200 |
commit | 6410e93aa52a7b406bcbdaecc05a67a2030e4a27 (patch) | |
tree | 721a04018dbfe2fb7935d6f8d5c89b5c4692bd14 /bgpd/bgp_open.c | |
parent | quagga: quagga-debian-upgrade.patch (diff) | |
download | frr-6410e93aa52a7b406bcbdaecc05a67a2030e4a27.tar.xz frr-6410e93aa52a7b406bcbdaecc05a67a2030e4a27.zip |
bgpd-hostname-cap.patch
bgpd: Exchange hostname capability and display hostnames in outputs
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>
Diffstat (limited to 'bgpd/bgp_open.c')
-rw-r--r-- | bgpd/bgp_open.c | 134 |
1 files changed, 133 insertions, 1 deletions
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index de24d435a..9fcd64bd2 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -451,7 +451,86 @@ bgp_capability_addpath (struct peer *peer, struct capability_header *hdr) return 0; } -static const struct message capcode_str[] = +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" }, { CAPABILITY_CODE_REFRESH, "Route Refresh" }, @@ -463,6 +542,7 @@ static const struct message capcode_str[] = { CAPABILITY_CODE_DYNAMIC_OLD, "Dynamic (Old)" }, { CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)" }, { CAPABILITY_CODE_ORF_OLD, "ORF (Old)" }, + { CAPABILITY_CODE_HOSTNAME, "Hostname" }, }; static const int capcode_str_max = array_size(capcode_str); @@ -479,6 +559,7 @@ static const size_t cap_minsizes[] = [CAPABILITY_CODE_DYNAMIC_OLD] = CAPABILITY_CODE_DYNAMIC_LEN, [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN, [CAPABILITY_CODE_ORF_OLD] = sizeof (struct capability_orf_entry), + [CAPABILITY_CODE_HOSTNAME] = CAPABILITY_CODE_MIN_HOSTNAME_LEN, }; /** @@ -543,6 +624,7 @@ bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability, case CAPABILITY_CODE_ADDPATH: case CAPABILITY_CODE_DYNAMIC: case CAPABILITY_CODE_DYNAMIC_OLD: + case CAPABILITY_CODE_HOSTNAME: /* Check length. */ if (caphdr.length < cap_minsizes[caphdr.code]) { @@ -617,6 +699,10 @@ bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability, if (bgp_capability_addpath (peer, &caphdr)) return -1; break; + case CAPABILITY_CODE_HOSTNAME: + if (bgp_capability_hostname (peer, &caphdr)) + return -1; + break; default: if (caphdr.code > 128) { @@ -951,6 +1037,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); @@ -1097,6 +1184,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_HOSTNAME); + 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); |