int ret;
union sockunion su;
struct bgp *bgp;
+ struct peer *peer;
bgp = vty->index;
ret = str2sockunion (peer_str, &su);
/* 'swpX' string */
if (ret < 0)
{
- return peer_lookup_by_conf_if (bgp, peer_str);
+ peer = peer_lookup_by_conf_if (bgp, peer_str);
+
+ if (!peer)
+ peer = peer_lookup_by_hostname (bgp, peer_str);
+
+ return peer;
}
else
return peer_lookup (bgp, &su);
from_peer->last_event = last_evt;
from_peer->last_major_event = last_maj_evt;
peer->remote_id = from_peer->remote_id;
+ if (from_peer->hostname != NULL)
+ peer->hostname = XSTRDUP(MTYPE_HOST, from_peer->hostname);
+ if (from_peer->domainname != NULL)
+ peer->domainname = XSTRDUP(MTYPE_HOST, from_peer->domainname);
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
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" },
{ 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);
[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,
};
/**
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])
{
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)
{
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);
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);
#define CAPABILITY_CODE_DYNAMIC_OLD 66 /* Dynamic Capability, deprecated since 2003 */
#define CAPABILITY_CODE_DYNAMIC 67 /* Dynamic Capability */
#define CAPABILITY_CODE_ADDPATH 69 /* Addpath Capability */
+#define CAPABILITY_CODE_FQDN 73 /* Advertise hostname capabilty */
#define CAPABILITY_CODE_ENHE 5 /* Extended Next Hop Encoding */
#define CAPABILITY_CODE_REFRESH_OLD 128 /* Route Refresh Capability(cisco) */
#define CAPABILITY_CODE_ORF_OLD 130 /* Cooperative Route Filtering Capability(cisco) */
+
/* Capability Length */
#define CAPABILITY_CODE_MP_LEN 4
#define CAPABILITY_CODE_REFRESH_LEN 0
#define CAPABILITY_CODE_AS4_LEN 4
#define CAPABILITY_CODE_ADDPATH_LEN 4
#define CAPABILITY_CODE_ENHE_LEN 6 /* NRLI AFI = 2, SAFI = 2, Nexthop AFI = 2 */
+#define CAPABILITY_CODE_MIN_FQDN_LEN 2
/* Cooperative Route Filtering Capability. */
json_object_string_add(json_peer, "peerId", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN));
json_object_string_add(json_peer, "routerId", inet_ntop (AF_INET, &binfo->peer->remote_id, buf1, BUFSIZ));
+ if (binfo->peer->hostname)
+ json_object_string_add(json_peer, "hostname", binfo->peer->hostname);
+
+ if (binfo->peer->domainname)
+ json_object_string_add(json_peer, "domainname", binfo->peer->domainname);
+
if (binfo->peer->conf_if)
json_object_string_add(json_peer, "interface", binfo->peer->conf_if);
}
else
{
if (binfo->peer->conf_if)
- vty_out (vty, " from %s", binfo->peer->conf_if);
+ {
+ if (binfo->peer->hostname &&
+ bgp_flag_check(binfo->peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
+ vty_out (vty, " from %s(%s)", binfo->peer->hostname,
+ binfo->peer->conf_if);
+ else
+ vty_out (vty, " from %s", binfo->peer->conf_if);
+ }
else
- vty_out (vty, " from %s", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN));
+ {
+ if (binfo->peer->hostname &&
+ bgp_flag_check(binfo->peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
+ vty_out (vty, " from %s(%s)", binfo->peer->hostname,
+ binfo->peer->host);
+ else
+ vty_out (vty, " from %s", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN));
+ }
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
vty_out (vty, " (%s)", inet_ntoa (attr->extra->originator_id));
*/
json_peer = json_object_new_object();
+ if (peer->hostname)
+ json_object_string_add(json_peer, "hostname", peer->hostname);
+
if (!json_adv_to)
json_adv_to = json_object_new_object();
if (! first)
vty_out (vty, " Advertised to non peer-group peers:%s ", VTY_NEWLINE);
- if (peer->conf_if)
- vty_out (vty, " %s", peer->conf_if);
- else
- vty_out (vty, " %s", sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN));
+ if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
+ {
+ if (peer->conf_if)
+ vty_out (vty, " %s(%s)", peer->hostname, peer->conf_if);
+ else
+ vty_out (vty, " %s(%s)", peer->hostname,
+ sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN));
+ }
+ else
+ {
+ if (peer->conf_if)
+ vty_out (vty, " %s", peer->conf_if);
+ else
+ vty_out (vty, " %s", sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN));
+ }
}
first = 1;
}
peer = peer_lookup_by_conf_if (bgp, ip_str);
if (!peer)
{
- if (use_json)
+ peer = peer_lookup_by_hostname(bgp, ip_str);
+
+ if (!peer)
{
- json_object *json_no = NULL;
- json_no = json_object_new_object();
- json_object_string_add(json_no, "malformedAddressOrName", ip_str);
- vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
- json_object_free(json_no);
+ if (use_json)
+ {
+ json_object *json_no = NULL;
+ json_no = json_object_new_object();
+ json_object_string_add(json_no, "malformedAddressOrName", ip_str);
+ vty_out (vty, "%s%s", json_object_to_json_string(json_no), VTY_NEWLINE);
+ json_object_free(json_no);
+ }
+ else
+ vty_out (vty, "%% Malformed address or name: %s%s", ip_str, VTY_NEWLINE);
+ return NULL;
}
- else
- vty_out (vty, "%% Malformed address or name: %s%s", ip_str, VTY_NEWLINE);
- return NULL;
}
return peer;
}
}
else
{
- vty_out (vty, "Prefix counts for %s, %s%s",
- peer->host, afi_safi_print (afi, safi), VTY_NEWLINE);
+
+ if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
+ {
+ vty_out (vty, "Prefix counts for %s/%s, %s%s",
+ peer->hostname, peer->host, afi_safi_print (afi, safi),
+ VTY_NEWLINE);
+ }
+ else
+ {
+ vty_out (vty, "Prefix counts for %s, %s%s",
+ peer->host, afi_safi_print (afi, safi), VTY_NEWLINE);
+ }
+
vty_out (vty, "PfxCt: %ld%s", peer->pcount[afi][safi], VTY_NEWLINE);
vty_out (vty, "%sCounts from RIB table walk:%s%s",
VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
peer = peer_lookup_by_conf_if (bgp, ip_str);
if (!peer)
{
- vty_out (vty, "%% Malformed address or name: %s%s", ip_str, VTY_NEWLINE);
- return NULL;
+ if ((peer = peer_lookup_by_hostname(bgp, ip_str)) == NULL)
+ {
+ vty_out (vty, "%% Malformed address or name: %s%s", ip_str, VTY_NEWLINE);
+ return NULL;
+ }
}
}
else
peer = peer_lookup_by_conf_if (bgp, arg);
if (!peer)
{
- vty_out (vty, "Malformed address or name: %s%s", arg, VTY_NEWLINE);
- return CMD_WARNING;
+ peer = peer_lookup_by_hostname(bgp, arg);
+ if (!peer)
+ {
+ vty_out (vty, "Malformed address or name: %s%s", arg, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
}
}
else
return CMD_SUCCESS;
}
+/* Display hostname in certain command outputs */
+DEFUN (bgp_default_show_hostname,
+ bgp_default_show_hostname_cmd,
+ "bgp default show-hostname",
+ "BGP specific commands\n"
+ "Configure BGP defaults\n"
+ "Show hostname in certain command ouputs\n")
+{
+ struct bgp *bgp;
+
+ bgp = vty->index;
+ bgp_flag_set (bgp, BGP_FLAG_SHOW_HOSTNAME);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_default_show_hostname,
+ no_bgp_default_show_hostname_cmd,
+ "no bgp default show-hostname",
+ NO_STR
+ "BGP specific commands\n"
+ "Configure BGP defaults\n"
+ "Show hostname in certain command ouputs\n")
+{
+ struct bgp *bgp;
+
+ bgp = vty->index;
+ bgp_flag_unset (bgp, BGP_FLAG_SHOW_HOSTNAME);
+ return CMD_SUCCESS;
+}
+
/* "bgp import-check" configuration. */
DEFUN (bgp_network_import_check,
bgp_network_import_check_cmd,
if (peer_dynamic_neighbor(peer))
json_object_boolean_true_add(json_peer, "dynamicPeer");
+ if (peer->hostname)
+ json_object_string_add(json_peer, "hostname", peer->hostname);
+
+ if (peer->domainname)
+ json_object_string_add(json_peer, "domainname", peer->domainname);
+
json_object_int_add(json_peer, "remoteAs", peer->as);
json_object_int_add(json_peer, "version", 4);
json_object_int_add(json_peer, "msgRcvd",
dn_flag[0] = '*';
}
- len = vty_out (vty, "%s%s", dn_flag, peer->host);
+ if (peer->hostname && bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME))
+ len = vty_out (vty, "%s%s(%s)", dn_flag, peer->hostname,
+ peer->host);
+ else
+ len = vty_out (vty, "%s%s", dn_flag, peer->host);
len = 16 - len;
if (len < 1)
vty_out (vty, " Description: %s%s", p->desc, VTY_NEWLINE);
}
+ if (p->hostname)
+ {
+ if (p->domainname && (p->domainname[0] != '\0'))
+ vty_out(vty, "Hostname: %s.%s%s", p->hostname, p->domainname,
+ VTY_NEWLINE);
+ else
+ vty_out(vty, "Hostname: %s%s", p->hostname, VTY_NEWLINE);
+ }
+
/* Peer-group */
if (p->group)
{
vty_out (vty, "%s", VTY_NEWLINE);
}
+ /* Hostname capability */
+ if (CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_ADV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_RCV))
+ {
+ vty_out (vty, " Hostname Capability:");
+ if (CHECK_FLAG (p->cap, PEER_CAP_HOSTNAME_ADV))
+ vty_out (vty, " advertised");
+ if (CHECK_FLAG (p->cap, PEER_CAP_HOSTNAME_RCV))
+ vty_out (vty, " %sreceived",
+ CHECK_FLAG (p->cap, PEER_CAP_HOSTNAME_ADV) ? "and " : "");
+ vty_out (vty, "%s", VTY_NEWLINE);
+ }
+
/* Gracefull Restart */
if (CHECK_FLAG (p->cap, PEER_CAP_RESTART_RCV)
|| CHECK_FLAG (p->cap, PEER_CAP_RESTART_ADV))
install_element (BGP_NODE, &no_bgp_default_local_preference_cmd);
install_element (BGP_NODE, &no_bgp_default_local_preference_val_cmd);
+ /* bgp default show-hostname */
+ install_element (BGP_NODE, &bgp_default_show_hostname_cmd);
+ install_element (BGP_NODE, &no_bgp_default_show_hostname_cmd);
+
/* "bgp default subgroup-pkt-queue-max" commands. */
install_element (BGP_NODE, &bgp_default_subgroup_pkt_queue_max_cmd);
install_element (BGP_NODE, &no_bgp_default_subgroup_pkt_queue_max_cmd);
FOREACH_AFI_SAFI (afi, safi)
peer_af_delete (peer, afi, safi);
+
+ if (peer->hostname)
+ XFREE(MTYPE_HOST, peer->hostname);
+ if (peer->domainname)
+ XFREE(MTYPE_HOST, peer->domainname);
+
peer_unlock (peer); /* initial reference */
return 0;
return NULL;
}
+struct peer *
+peer_lookup_by_hostname (struct bgp *bgp, const char *hostname)
+{
+ struct peer *peer;
+ struct listnode *node, *nnode;
+
+ if (!hostname)
+ return NULL;
+
+ if (bgp != NULL)
+ {
+ for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+ if (peer->hostname && !strcmp(peer->hostname, hostname)
+ && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
+ return peer;
+ }
+ else if (bm->bgp != NULL)
+ {
+ struct listnode *bgpnode, *nbgpnode;
+
+ for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
+ for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+ if (peer->hostname && !strcmp(peer->hostname, hostname)
+ && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
+ return peer;
+ }
+ return NULL;
+}
+
struct peer *
peer_lookup (struct bgp *bgp, union sockunion *su)
{
vty_out (vty, " bgp default local-preference %d%s",
bgp->default_local_pref, VTY_NEWLINE);
+ /* BGP default show-hostname */
+ if (bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME))
+ vty_out (vty, " bgp default show-hostname%s", VTY_NEWLINE);
+
/* BGP default subgroup-pkt-queue-max. */
if (bgp->default_subgroup_pkt_queue_max != BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX)
vty_out (vty, " bgp default subgroup-pkt-queue-max %d%s",
#include "routemap.h"
#include "linklist.h"
+#define BGP_MAX_HOSTNAME 64 /* Linux max, is larger than most other sys */
+
struct update_subgroup;
struct bpacket;
#define BGP_FLAG_MULTIPATH_RELAX_NO_AS_SET (1 << 17)
#define BGP_FLAG_FORCE_STATIC_PROCESS (1 << 18)
#define BGP_FLAG_IMPORT_CHECK_EXACT_MATCH (1 << 19)
+#define BGP_FLAG_SHOW_HOSTNAME (1 << 20)
/* BGP Per AF flags */
u_int16_t af_flags[AFI_MAX][SAFI_MAX];
#define PEER_CAP_ADDPATH_RCV (1 << 12) /* addpath received */
#define PEER_CAP_ENHE_ADV (1 << 13) /* Extended nexthop advertised */
#define PEER_CAP_ENHE_RCV (1 << 14) /* Extended nexthop received */
+#define PEER_CAP_HOSTNAME_ADV (1 << 15) /* hostname advertised */
+#define PEER_CAP_HOSTNAME_RCV (1 << 16) /* hostname received */
/* Capability flags (reset in bgp_stop) */
- u_int16_t af_cap[AFI_MAX][SAFI_MAX];
+ u_int32_t af_cap[AFI_MAX][SAFI_MAX];
#define PEER_CAP_ORF_PREFIX_SM_ADV (1 << 0) /* send-mode advertised */
#define PEER_CAP_ORF_PREFIX_RM_ADV (1 << 1) /* receive-mode advertised */
#define PEER_CAP_ORF_PREFIX_SM_RCV (1 << 2) /* send-mode received */
/* peer specific BFD information */
struct bfd_info *bfd_info;
+
+ /* hostname and domainname advertised by host */
+ char *hostname;
+ char *domainname;
};
#define PEER_PASSWORD_MINLEN (1)
extern struct bgp *bgp_lookup_by_name (const char *);
extern struct peer *peer_lookup (struct bgp *, union sockunion *);
extern struct peer *peer_lookup_by_conf_if (struct bgp *, const char *);
+extern struct peer *peer_lookup_by_hostname(struct bgp *, const char *);
extern struct peer *peer_conf_interface_get(struct bgp *, const char *, afi_t,
safi_t, int v6only);
extern void bgp_peer_conf_if_to_su_update (struct peer *);