mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-02 15:34:30 +00:00
Merge pull request #1056 from opensourcerouting/oldbits-0
"pathspace" options, vtysh-suid-cleanups, "vty_frame()"
This commit is contained in:
commit
32592ffb4f
@ -1321,7 +1321,7 @@ interface_config_write (struct vty *vty)
|
||||
int write = 0;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (vrf_iflist(VRF_DEFAULT), node, ifp)) {
|
||||
vty_out (vty, "interface %s\n",ifp->name);
|
||||
vty_frame (vty, "interface %s\n",ifp->name);
|
||||
if (ifp->desc)
|
||||
vty_out (vty, " description %s\n",ifp->desc);
|
||||
babel_interface_nfo *babel_ifp = babel_get_if_nfo (ifp);
|
||||
@ -1377,7 +1377,7 @@ interface_config_write (struct vty *vty)
|
||||
write++;
|
||||
}
|
||||
}
|
||||
vty_out (vty, "!\n");
|
||||
vty_endframe (vty, "!\n");
|
||||
write++;
|
||||
}
|
||||
return write;
|
||||
|
@ -50,11 +50,6 @@ struct vni_walk_ctx {
|
||||
json_object *json;
|
||||
};
|
||||
|
||||
struct evpn_config_write {
|
||||
int write;
|
||||
struct vty *vty;
|
||||
};
|
||||
|
||||
#if defined(HAVE_CUMULUS)
|
||||
static void display_import_rt(struct vty *vty, struct irt_node *irt,
|
||||
json_object *json)
|
||||
@ -587,155 +582,150 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
|
||||
if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
|
||||
continue;
|
||||
|
||||
if ((table = rn->info) != NULL) {
|
||||
rd_header = 1;
|
||||
if ((table = rn->info) == NULL)
|
||||
continue;
|
||||
|
||||
for (rm = bgp_table_top(table); rm;
|
||||
rm = bgp_route_next(rm))
|
||||
for (ri = rm->info; ri; ri = ri->next) {
|
||||
total_count++;
|
||||
if (type == bgp_show_type_neighbor) {
|
||||
union sockunion *su =
|
||||
output_arg;
|
||||
rd_header = 1;
|
||||
|
||||
if (ri->peer->su_remote == NULL
|
||||
|| !sockunion_same(
|
||||
ri->peer->su_remote,
|
||||
su))
|
||||
continue;
|
||||
}
|
||||
if (header == 0) {
|
||||
if (use_json) {
|
||||
if (option
|
||||
== SHOW_DISPLAY_TAGS) {
|
||||
json_object_int_add(
|
||||
json,
|
||||
"bgpTableVersion",
|
||||
0);
|
||||
json_object_string_add(
|
||||
json,
|
||||
"bgpLocalRouterId",
|
||||
inet_ntoa(
|
||||
bgp->router_id));
|
||||
json_object_object_add(
|
||||
json,
|
||||
"bgpStatusCodes",
|
||||
json_scode);
|
||||
json_object_object_add(
|
||||
json,
|
||||
"bgpOriginCodes",
|
||||
json_ocode);
|
||||
}
|
||||
} else {
|
||||
if (option
|
||||
== SHOW_DISPLAY_TAGS)
|
||||
vty_out(vty,
|
||||
V4_HEADER_TAG);
|
||||
else if (
|
||||
option
|
||||
== SHOW_DISPLAY_OVERLAY)
|
||||
vty_out(vty,
|
||||
V4_HEADER_OVERLAY);
|
||||
else {
|
||||
vty_out(vty,
|
||||
"BGP table version is 0, local router ID is %s\n",
|
||||
inet_ntoa(
|
||||
bgp->router_id));
|
||||
vty_out(vty,
|
||||
"Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
|
||||
vty_out(vty,
|
||||
"Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
|
||||
vty_out(vty,
|
||||
V4_HEADER);
|
||||
}
|
||||
}
|
||||
header = 0;
|
||||
}
|
||||
if (rd_header) {
|
||||
u_int16_t type;
|
||||
struct rd_as rd_as;
|
||||
struct rd_ip rd_ip;
|
||||
u_char *pnt;
|
||||
for (rm = bgp_table_top(table); rm;
|
||||
rm = bgp_route_next(rm))
|
||||
for (ri = rm->info; ri; ri = ri->next) {
|
||||
total_count++;
|
||||
if (type == bgp_show_type_neighbor) {
|
||||
union sockunion *su =
|
||||
output_arg;
|
||||
|
||||
pnt = rn->p.u.val;
|
||||
|
||||
/* Decode RD type. */
|
||||
type = decode_rd_type(pnt);
|
||||
/* Decode RD value. */
|
||||
if (type == RD_TYPE_AS)
|
||||
decode_rd_as(pnt + 2,
|
||||
&rd_as);
|
||||
else if (type == RD_TYPE_AS4)
|
||||
decode_rd_as4(pnt + 2,
|
||||
&rd_as);
|
||||
else if (type == RD_TYPE_IP)
|
||||
decode_rd_ip(pnt + 2,
|
||||
&rd_ip);
|
||||
if (use_json) {
|
||||
char buffer[BUFSIZ];
|
||||
if (type == RD_TYPE_AS
|
||||
|| type == RD_TYPE_AS4)
|
||||
sprintf(buffer,
|
||||
"%u:%d",
|
||||
rd_as.as,
|
||||
rd_as.val);
|
||||
else if (type
|
||||
== RD_TYPE_IP)
|
||||
sprintf(buffer,
|
||||
"%s:%d",
|
||||
inet_ntoa(
|
||||
rd_ip.ip),
|
||||
rd_ip.val);
|
||||
json_object_string_add(
|
||||
json_nroute,
|
||||
"routeDistinguisher",
|
||||
buffer);
|
||||
} else {
|
||||
vty_out(vty,
|
||||
"Route Distinguisher: ");
|
||||
if (type == RD_TYPE_AS)
|
||||
vty_out(vty,
|
||||
"as2 %u:%d",
|
||||
rd_as.as,
|
||||
rd_as.val);
|
||||
else if (type
|
||||
== RD_TYPE_AS4)
|
||||
vty_out(vty,
|
||||
"as4 %u:%d",
|
||||
rd_as.as,
|
||||
rd_as.val);
|
||||
else if (type
|
||||
== RD_TYPE_IP)
|
||||
vty_out(vty,
|
||||
"ip %s:%d",
|
||||
inet_ntoa(
|
||||
rd_ip.ip),
|
||||
rd_ip.val);
|
||||
vty_out(vty, "\n\n");
|
||||
}
|
||||
rd_header = 0;
|
||||
}
|
||||
if (use_json)
|
||||
json_array =
|
||||
json_object_new_array();
|
||||
else
|
||||
json_array = NULL;
|
||||
if (option == SHOW_DISPLAY_TAGS)
|
||||
route_vty_out_tag(
|
||||
vty, &rm->p, ri, 0,
|
||||
SAFI_EVPN, json_array);
|
||||
else if (option == SHOW_DISPLAY_OVERLAY)
|
||||
route_vty_out_overlay(
|
||||
vty, &rm->p, ri, 0,
|
||||
json_array);
|
||||
else
|
||||
route_vty_out(vty, &rm->p, ri,
|
||||
0, SAFI_EVPN,
|
||||
json_array);
|
||||
output_count++;
|
||||
if (ri->peer->su_remote == NULL
|
||||
|| !sockunion_same(
|
||||
ri->peer->su_remote,
|
||||
su))
|
||||
continue;
|
||||
}
|
||||
/* XXX json */
|
||||
}
|
||||
if (header == 0) {
|
||||
if (use_json) {
|
||||
if (option
|
||||
== SHOW_DISPLAY_TAGS) {
|
||||
json_object_int_add(
|
||||
json,
|
||||
"bgpTableVersion",
|
||||
0);
|
||||
json_object_string_add(
|
||||
json,
|
||||
"bgpLocalRouterId",
|
||||
inet_ntoa(
|
||||
bgp->router_id));
|
||||
json_object_object_add(
|
||||
json,
|
||||
"bgpStatusCodes",
|
||||
json_scode);
|
||||
json_object_object_add(
|
||||
json,
|
||||
"bgpOriginCodes",
|
||||
json_ocode);
|
||||
}
|
||||
} else {
|
||||
if (option
|
||||
== SHOW_DISPLAY_TAGS)
|
||||
vty_out(vty,
|
||||
V4_HEADER_TAG);
|
||||
else if (
|
||||
option
|
||||
== SHOW_DISPLAY_OVERLAY)
|
||||
vty_out(vty,
|
||||
V4_HEADER_OVERLAY);
|
||||
else {
|
||||
vty_out(vty,
|
||||
"BGP table version is 0, local router ID is %s\n",
|
||||
inet_ntoa(
|
||||
bgp->router_id));
|
||||
vty_out(vty,
|
||||
"Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
|
||||
vty_out(vty,
|
||||
"Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
|
||||
vty_out(vty,
|
||||
V4_HEADER);
|
||||
}
|
||||
}
|
||||
header = 0;
|
||||
}
|
||||
if (rd_header) {
|
||||
u_int16_t type;
|
||||
struct rd_as rd_as;
|
||||
struct rd_ip rd_ip;
|
||||
u_char *pnt;
|
||||
|
||||
pnt = rn->p.u.val;
|
||||
|
||||
/* Decode RD type. */
|
||||
type = decode_rd_type(pnt);
|
||||
/* Decode RD value. */
|
||||
if (type == RD_TYPE_AS)
|
||||
decode_rd_as(pnt + 2, &rd_as);
|
||||
else if (type == RD_TYPE_AS4)
|
||||
decode_rd_as4(pnt + 2, &rd_as);
|
||||
else if (type == RD_TYPE_IP)
|
||||
decode_rd_ip(pnt + 2, &rd_ip);
|
||||
if (use_json) {
|
||||
char buffer[BUFSIZ];
|
||||
if (type == RD_TYPE_AS
|
||||
|| type == RD_TYPE_AS4)
|
||||
sprintf(buffer,
|
||||
"%u:%d",
|
||||
rd_as.as,
|
||||
rd_as.val);
|
||||
else if (type
|
||||
== RD_TYPE_IP)
|
||||
sprintf(buffer,
|
||||
"%s:%d",
|
||||
inet_ntoa(
|
||||
rd_ip.ip),
|
||||
rd_ip.val);
|
||||
json_object_string_add(
|
||||
json_nroute,
|
||||
"routeDistinguisher",
|
||||
buffer);
|
||||
} else {
|
||||
vty_out(vty,
|
||||
"Route Distinguisher: ");
|
||||
if (type == RD_TYPE_AS)
|
||||
vty_out(vty,
|
||||
"as2 %u:%d",
|
||||
rd_as.as,
|
||||
rd_as.val);
|
||||
else if (type
|
||||
== RD_TYPE_AS4)
|
||||
vty_out(vty,
|
||||
"as4 %u:%d",
|
||||
rd_as.as,
|
||||
rd_as.val);
|
||||
else if (type
|
||||
== RD_TYPE_IP)
|
||||
vty_out(vty,
|
||||
"ip %s:%d",
|
||||
inet_ntoa(
|
||||
rd_ip.ip),
|
||||
rd_ip.val);
|
||||
vty_out(vty, "\n\n");
|
||||
}
|
||||
rd_header = 0;
|
||||
}
|
||||
if (use_json)
|
||||
json_array = json_object_new_array();
|
||||
else
|
||||
json_array = NULL;
|
||||
if (option == SHOW_DISPLAY_TAGS)
|
||||
route_vty_out_tag(vty, &rm->p, ri, 0,
|
||||
SAFI_EVPN,
|
||||
json_array);
|
||||
else if (option == SHOW_DISPLAY_OVERLAY)
|
||||
route_vty_out_overlay(vty, &rm->p, ri,
|
||||
0, json_array);
|
||||
else
|
||||
route_vty_out(vty, &rm->p, ri, 0,
|
||||
SAFI_EVPN, json_array);
|
||||
output_count++;
|
||||
}
|
||||
/* XXX json */
|
||||
}
|
||||
if (output_count == 0)
|
||||
vty_out(vty, "No prefixes displayed, %ld exist\n", total_count);
|
||||
@ -2125,17 +2115,14 @@ static void evpn_unset_advertise_all_vni(struct bgp *bgp)
|
||||
}
|
||||
#endif /* HAVE_CUMULUS */
|
||||
|
||||
static void write_vni_config(struct vty *vty, struct bgpevpn *vpn, int *write)
|
||||
static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
|
||||
{
|
||||
char buf1[INET6_ADDRSTRLEN];
|
||||
afi_t afi = AFI_L2VPN;
|
||||
safi_t safi = SAFI_EVPN;
|
||||
char *ecom_str;
|
||||
struct listnode *node, *nnode;
|
||||
struct ecommunity *ecom;
|
||||
|
||||
if (is_vni_configured(vpn)) {
|
||||
bgp_config_write_family_header(vty, afi, safi, write);
|
||||
vty_out(vty, " vni %d\n", vpn->vni);
|
||||
if (is_rd_configured(vpn))
|
||||
vty_out(vty, " rd %s\n",
|
||||
@ -2171,10 +2158,10 @@ static void write_vni_config(struct vty *vty, struct bgpevpn *vpn, int *write)
|
||||
}
|
||||
|
||||
static void write_vni_config_for_entry(struct hash_backet *backet,
|
||||
struct evpn_config_write *cfg)
|
||||
struct vty *vty)
|
||||
{
|
||||
struct bgpevpn *vpn = (struct bgpevpn *)backet->data;
|
||||
write_vni_config(cfg->vty, vpn, &cfg->write);
|
||||
write_vni_config(vty, vpn);
|
||||
}
|
||||
|
||||
#if defined(HAVE_CUMULUS)
|
||||
@ -3326,29 +3313,19 @@ DEFUN (no_bgp_evpn_vni_rt_without_val,
|
||||
* Output EVPN configuration information.
|
||||
*/
|
||||
void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
safi_t safi, int *write)
|
||||
safi_t safi)
|
||||
{
|
||||
struct evpn_config_write cfg;
|
||||
|
||||
if (bgp->vnihash) {
|
||||
cfg.write = *write;
|
||||
cfg.vty = vty;
|
||||
if (bgp->vnihash)
|
||||
hash_iterate(bgp->vnihash,
|
||||
(void (*)(struct hash_backet *,
|
||||
void *))write_vni_config_for_entry,
|
||||
&cfg);
|
||||
*write = cfg.write;
|
||||
}
|
||||
vty);
|
||||
|
||||
if (bgp->advertise_all_vni) {
|
||||
bgp_config_write_family_header(vty, afi, safi, write);
|
||||
if (bgp->advertise_all_vni)
|
||||
vty_out(vty, " advertise-all-vni\n");
|
||||
}
|
||||
|
||||
if (bgp->advertise_gw_macip) {
|
||||
bgp_config_write_family_header(vty, afi, safi, write);
|
||||
if (bgp->advertise_gw_macip)
|
||||
vty_out(vty, " advertise-default-gw\n");
|
||||
}
|
||||
}
|
||||
|
||||
void bgp_ethernetvpn_init(void)
|
||||
|
@ -22,7 +22,7 @@
|
||||
#define _FRR_BGP_EVPN_VTY_H
|
||||
|
||||
extern void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp,
|
||||
afi_t afi, safi_t safi, int *write);
|
||||
afi_t afi, safi_t safi);
|
||||
extern void bgp_ethernetvpn_init(void);
|
||||
|
||||
#define L2VPN_HELP_STR "Layer 2 Virtual Private Network\n"
|
||||
|
955
bgpd/bgp_route.c
955
bgpd/bgp_route.c
File diff suppressed because it is too large
Load Diff
@ -369,12 +369,9 @@ extern void bgp_process(struct bgp *, struct bgp_node *, afi_t, safi_t);
|
||||
* queue element with NULL bgp node.
|
||||
*/
|
||||
extern void bgp_add_eoiu_mark(struct bgp *);
|
||||
extern int bgp_config_write_table_map(struct vty *, struct bgp *, afi_t, safi_t,
|
||||
int *);
|
||||
extern int bgp_config_write_network(struct vty *, struct bgp *, afi_t, safi_t,
|
||||
int *);
|
||||
extern int bgp_config_write_distance(struct vty *, struct bgp *, afi_t, safi_t,
|
||||
int *);
|
||||
extern void bgp_config_write_table_map(struct vty *, struct bgp *, afi_t, safi_t);
|
||||
extern void bgp_config_write_network(struct vty *, struct bgp *, afi_t, safi_t);
|
||||
extern void bgp_config_write_distance(struct vty *, struct bgp *, afi_t, safi_t);
|
||||
|
||||
extern void bgp_aggregate_increment(struct bgp *, struct prefix *,
|
||||
struct bgp_info *, afi_t, safi_t);
|
||||
|
679
bgpd/bgp_vty.c
679
bgpd/bgp_vty.c
@ -1279,7 +1279,7 @@ static int bgp_update_delay_deconfig_vty(struct vty *vty)
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
int bgp_config_write_update_delay(struct vty *vty, struct bgp *bgp)
|
||||
void bgp_config_write_update_delay(struct vty *vty, struct bgp *bgp)
|
||||
{
|
||||
if (bgp->v_update_delay != BGP_UPDATE_DELAY_DEF) {
|
||||
vty_out(vty, " update-delay %d", bgp->v_update_delay);
|
||||
@ -1287,8 +1287,6 @@ int bgp_config_write_update_delay(struct vty *vty, struct bgp *bgp)
|
||||
vty_out(vty, " %d", bgp->v_establish_wait);
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1342,12 +1340,10 @@ static int bgp_wpkt_quanta_config_vty(struct vty *vty, const char *num,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
int bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp)
|
||||
void bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp)
|
||||
{
|
||||
if (bgp->wpkt_quanta != BGP_WRITE_PACKET_MAX)
|
||||
vty_out(vty, " write-quanta %d\n", bgp->wpkt_quanta);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1374,12 +1370,10 @@ DEFUN (no_bgp_wpkt_quanta,
|
||||
return bgp_wpkt_quanta_config_vty(vty, argv[idx_number]->arg, 0);
|
||||
}
|
||||
|
||||
int bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp)
|
||||
void bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp)
|
||||
{
|
||||
if (bgp->coalesce_time != BGP_DEFAULT_SUBGROUP_COALESCE_TIME)
|
||||
vty_out(vty, " coalesce-time %u\n", bgp->coalesce_time);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1503,17 +1497,15 @@ ALIAS_HIDDEN(no_bgp_maxpaths_ibgp, no_bgp_maxpaths_ibgp_hidden_cmd,
|
||||
"Number of paths\n"
|
||||
"Match the cluster length\n")
|
||||
|
||||
int bgp_config_write_maxpaths(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
safi_t safi, int *write)
|
||||
void bgp_config_write_maxpaths(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
safi_t safi)
|
||||
{
|
||||
if (bgp->maxpaths[afi][safi].maxpaths_ebgp != MULTIPATH_NUM) {
|
||||
bgp_config_write_family_header(vty, afi, safi, write);
|
||||
vty_out(vty, " maximum-paths %d\n",
|
||||
bgp->maxpaths[afi][safi].maxpaths_ebgp);
|
||||
}
|
||||
|
||||
if (bgp->maxpaths[afi][safi].maxpaths_ibgp != MULTIPATH_NUM) {
|
||||
bgp_config_write_family_header(vty, afi, safi, write);
|
||||
vty_out(vty, " maximum-paths ibgp %d",
|
||||
bgp->maxpaths[afi][safi].maxpaths_ibgp);
|
||||
if (CHECK_FLAG(bgp->maxpaths[afi][safi].ibgp_flags,
|
||||
@ -1521,8 +1513,6 @@ int bgp_config_write_maxpaths(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
vty_out(vty, " equal-cluster-length");
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* BGP timers. */
|
||||
@ -2459,7 +2449,7 @@ DEFUN (no_bgp_listen_range,
|
||||
return bgp_vty_return(vty, ret);
|
||||
}
|
||||
|
||||
int bgp_config_write_listen(struct vty *vty, struct bgp *bgp)
|
||||
void bgp_config_write_listen(struct vty *vty, struct bgp *bgp)
|
||||
{
|
||||
struct peer_group *group;
|
||||
struct listnode *node, *nnode, *rnode, *nrnode;
|
||||
@ -2482,8 +2472,6 @@ int bgp_config_write_listen(struct vty *vty, struct bgp *bgp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -6675,368 +6663,369 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
|
||||
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
|
||||
continue;
|
||||
|
||||
if (peer->afc[afi][safi]) {
|
||||
if (!count) {
|
||||
unsigned long ents;
|
||||
char memstrbuf[MTYPE_MEMSTR_LEN];
|
||||
int vrf_id_ui;
|
||||
if (!peer->afc[afi][safi])
|
||||
continue;
|
||||
|
||||
vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN)
|
||||
? -1
|
||||
: bgp->vrf_id;
|
||||
if (!count) {
|
||||
unsigned long ents;
|
||||
char memstrbuf[MTYPE_MEMSTR_LEN];
|
||||
int vrf_id_ui;
|
||||
|
||||
/* Usage summary and header */
|
||||
vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN)
|
||||
? -1
|
||||
: bgp->vrf_id;
|
||||
|
||||
/* Usage summary and header */
|
||||
if (use_json) {
|
||||
json_object_string_add(
|
||||
json, "routerId",
|
||||
inet_ntoa(bgp->router_id));
|
||||
json_object_int_add(json, "as",
|
||||
bgp->as);
|
||||
json_object_int_add(json, "vrfId",
|
||||
vrf_id_ui);
|
||||
json_object_string_add(
|
||||
json, "vrfName",
|
||||
(bgp->inst_type
|
||||
== BGP_INSTANCE_TYPE_DEFAULT)
|
||||
? "Default"
|
||||
: bgp->name);
|
||||
} else {
|
||||
vty_out(vty,
|
||||
"BGP router identifier %s, local AS number %u vrf-id %d",
|
||||
inet_ntoa(bgp->router_id),
|
||||
bgp->as, vrf_id_ui);
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
|
||||
if (bgp_update_delay_configured(bgp)) {
|
||||
if (use_json) {
|
||||
json_object_string_add(
|
||||
json, "routerId",
|
||||
inet_ntoa(bgp->router_id));
|
||||
json_object_int_add(json, "as",
|
||||
bgp->as);
|
||||
json_object_int_add(json, "vrfId",
|
||||
vrf_id_ui);
|
||||
json_object_string_add(
|
||||
json, "vrfName",
|
||||
(bgp->inst_type
|
||||
== BGP_INSTANCE_TYPE_DEFAULT)
|
||||
? "Default"
|
||||
: bgp->name);
|
||||
} else {
|
||||
vty_out(vty,
|
||||
"BGP router identifier %s, local AS number %u vrf-id %d",
|
||||
inet_ntoa(bgp->router_id),
|
||||
bgp->as, vrf_id_ui);
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
json_object_int_add(
|
||||
json,
|
||||
"updateDelayLimit",
|
||||
bgp->v_update_delay);
|
||||
|
||||
if (bgp_update_delay_configured(bgp)) {
|
||||
if (use_json) {
|
||||
if (bgp->v_update_delay
|
||||
!= bgp->v_establish_wait)
|
||||
json_object_int_add(
|
||||
json,
|
||||
"updateDelayLimit",
|
||||
bgp->v_update_delay);
|
||||
"updateDelayEstablishWait",
|
||||
bgp->v_establish_wait);
|
||||
|
||||
if (bgp->v_update_delay
|
||||
!= bgp->v_establish_wait)
|
||||
json_object_int_add(
|
||||
json,
|
||||
"updateDelayEstablishWait",
|
||||
bgp->v_establish_wait);
|
||||
|
||||
if (bgp_update_delay_active(
|
||||
bgp)) {
|
||||
if (bgp_update_delay_active(
|
||||
bgp)) {
|
||||
json_object_string_add(
|
||||
json,
|
||||
"updateDelayFirstNeighbor",
|
||||
bgp->update_delay_begin_time);
|
||||
json_object_boolean_true_add(
|
||||
json,
|
||||
"updateDelayInProgress");
|
||||
} else {
|
||||
if (bgp->update_delay_over) {
|
||||
json_object_string_add(
|
||||
json,
|
||||
"updateDelayFirstNeighbor",
|
||||
bgp->update_delay_begin_time);
|
||||
json_object_boolean_true_add(
|
||||
json_object_string_add(
|
||||
json,
|
||||
"updateDelayInProgress");
|
||||
} else {
|
||||
if (bgp->update_delay_over) {
|
||||
json_object_string_add(
|
||||
json,
|
||||
"updateDelayFirstNeighbor",
|
||||
bgp->update_delay_begin_time);
|
||||
json_object_string_add(
|
||||
json,
|
||||
"updateDelayBestpathResumed",
|
||||
bgp->update_delay_end_time);
|
||||
json_object_string_add(
|
||||
json,
|
||||
"updateDelayZebraUpdateResume",
|
||||
bgp->update_delay_zebra_resume_time);
|
||||
json_object_string_add(
|
||||
json,
|
||||
"updateDelayPeerUpdateResume",
|
||||
bgp->update_delay_peers_resume_time);
|
||||
}
|
||||
"updateDelayBestpathResumed",
|
||||
bgp->update_delay_end_time);
|
||||
json_object_string_add(
|
||||
json,
|
||||
"updateDelayZebraUpdateResume",
|
||||
bgp->update_delay_zebra_resume_time);
|
||||
json_object_string_add(
|
||||
json,
|
||||
"updateDelayPeerUpdateResume",
|
||||
bgp->update_delay_peers_resume_time);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
vty_out(vty,
|
||||
"Read-only mode update-delay limit: %d seconds\n",
|
||||
bgp->v_update_delay);
|
||||
if (bgp->v_update_delay
|
||||
!= bgp->v_establish_wait)
|
||||
vty_out(vty,
|
||||
"Read-only mode update-delay limit: %d seconds\n",
|
||||
bgp->v_update_delay);
|
||||
if (bgp->v_update_delay
|
||||
!= bgp->v_establish_wait)
|
||||
vty_out(vty,
|
||||
" Establish wait: %d seconds\n",
|
||||
bgp->v_establish_wait);
|
||||
" Establish wait: %d seconds\n",
|
||||
bgp->v_establish_wait);
|
||||
|
||||
if (bgp_update_delay_active(
|
||||
bgp)) {
|
||||
if (bgp_update_delay_active(
|
||||
bgp)) {
|
||||
vty_out(vty,
|
||||
" First neighbor established: %s\n",
|
||||
bgp->update_delay_begin_time);
|
||||
vty_out(vty,
|
||||
" Delay in progress\n");
|
||||
} else {
|
||||
if (bgp->update_delay_over) {
|
||||
vty_out(vty,
|
||||
" First neighbor established: %s\n",
|
||||
bgp->update_delay_begin_time);
|
||||
vty_out(vty,
|
||||
" Delay in progress\n");
|
||||
} else {
|
||||
if (bgp->update_delay_over) {
|
||||
vty_out(vty,
|
||||
" First neighbor established: %s\n",
|
||||
bgp->update_delay_begin_time);
|
||||
vty_out(vty,
|
||||
" Best-paths resumed: %s\n",
|
||||
bgp->update_delay_end_time);
|
||||
vty_out(vty,
|
||||
" zebra update resumed: %s\n",
|
||||
bgp->update_delay_zebra_resume_time);
|
||||
vty_out(vty,
|
||||
" peers update resumed: %s\n",
|
||||
bgp->update_delay_peers_resume_time);
|
||||
}
|
||||
" Best-paths resumed: %s\n",
|
||||
bgp->update_delay_end_time);
|
||||
vty_out(vty,
|
||||
" zebra update resumed: %s\n",
|
||||
bgp->update_delay_zebra_resume_time);
|
||||
vty_out(vty,
|
||||
" peers update resumed: %s\n",
|
||||
bgp->update_delay_peers_resume_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (use_json) {
|
||||
if (bgp_maxmed_onstartup_configured(bgp)
|
||||
&& bgp->maxmed_active)
|
||||
json_object_boolean_true_add(
|
||||
json,
|
||||
"maxMedOnStartup");
|
||||
if (bgp->v_maxmed_admin)
|
||||
json_object_boolean_true_add(
|
||||
json,
|
||||
"maxMedAdministrative");
|
||||
|
||||
json_object_int_add(
|
||||
json, "tableVersion",
|
||||
bgp_table_version(
|
||||
bgp->rib[afi][safi]));
|
||||
|
||||
ents = bgp_table_count(
|
||||
bgp->rib[afi][safi]);
|
||||
json_object_int_add(json, "ribCount",
|
||||
ents);
|
||||
json_object_int_add(
|
||||
json, "ribMemory",
|
||||
ents * sizeof(struct bgp_node));
|
||||
|
||||
ents = listcount(bgp->peer);
|
||||
json_object_int_add(json, "peerCount",
|
||||
ents);
|
||||
json_object_int_add(
|
||||
json, "peerMemory",
|
||||
ents * sizeof(struct peer));
|
||||
|
||||
if ((ents = listcount(bgp->group))) {
|
||||
json_object_int_add(
|
||||
json, "peerGroupCount",
|
||||
ents);
|
||||
json_object_int_add(
|
||||
json, "peerGroupMemory",
|
||||
ents * sizeof(struct
|
||||
peer_group));
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||
BGP_CONFIG_DAMPENING))
|
||||
json_object_boolean_true_add(
|
||||
json,
|
||||
"dampeningEnabled");
|
||||
} else {
|
||||
if (bgp_maxmed_onstartup_configured(bgp)
|
||||
&& bgp->maxmed_active)
|
||||
vty_out(vty,
|
||||
"Max-med on-startup active\n");
|
||||
if (bgp->v_maxmed_admin)
|
||||
vty_out(vty,
|
||||
"Max-med administrative active\n");
|
||||
|
||||
vty_out(vty,
|
||||
"BGP table version %" PRIu64
|
||||
"\n",
|
||||
bgp_table_version(
|
||||
bgp->rib[afi][safi]));
|
||||
|
||||
ents = bgp_table_count(
|
||||
bgp->rib[afi][safi]);
|
||||
vty_out(vty,
|
||||
"RIB entries %ld, using %s of memory\n",
|
||||
ents,
|
||||
mtype_memstr(
|
||||
memstrbuf,
|
||||
sizeof(memstrbuf),
|
||||
ents * sizeof(struct
|
||||
bgp_node)));
|
||||
|
||||
/* Peer related usage */
|
||||
ents = listcount(bgp->peer);
|
||||
vty_out(vty,
|
||||
"Peers %ld, using %s of memory\n",
|
||||
ents,
|
||||
mtype_memstr(
|
||||
memstrbuf,
|
||||
sizeof(memstrbuf),
|
||||
ents * sizeof(struct
|
||||
peer)));
|
||||
|
||||
if ((ents = listcount(bgp->group)))
|
||||
vty_out(vty,
|
||||
"Peer groups %ld, using %s of memory\n",
|
||||
ents,
|
||||
mtype_memstr(
|
||||
memstrbuf,
|
||||
sizeof(memstrbuf),
|
||||
ents * sizeof(struct
|
||||
peer_group)));
|
||||
|
||||
if (CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||
BGP_CONFIG_DAMPENING))
|
||||
vty_out(vty,
|
||||
"Dampening enabled.\n");
|
||||
vty_out(vty, "\n");
|
||||
|
||||
/* Subtract 8 here because 'Neighbor' is
|
||||
* 8 characters */
|
||||
vty_out(vty, "Neighbor");
|
||||
vty_out(vty, "%*s",
|
||||
max_neighbor_width - 8, " ");
|
||||
vty_out(vty,
|
||||
"V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd\n");
|
||||
}
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
if (use_json) {
|
||||
json_peer = json_object_new_object();
|
||||
|
||||
if (peer_dynamic_neighbor(peer))
|
||||
if (bgp_maxmed_onstartup_configured(bgp)
|
||||
&& bgp->maxmed_active)
|
||||
json_object_boolean_true_add(
|
||||
json_peer, "dynamicPeer");
|
||||
json,
|
||||
"maxMedOnStartup");
|
||||
if (bgp->v_maxmed_admin)
|
||||
json_object_boolean_true_add(
|
||||
json,
|
||||
"maxMedAdministrative");
|
||||
|
||||
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",
|
||||
peer->open_in + peer->update_in
|
||||
+ peer->keepalive_in
|
||||
+ peer->notify_in
|
||||
+ peer->refresh_in
|
||||
+ peer->dynamic_cap_in);
|
||||
json, "tableVersion",
|
||||
bgp_table_version(
|
||||
bgp->rib[afi][safi]));
|
||||
|
||||
ents = bgp_table_count(
|
||||
bgp->rib[afi][safi]);
|
||||
json_object_int_add(json, "ribCount",
|
||||
ents);
|
||||
json_object_int_add(
|
||||
json_peer, "msgSent",
|
||||
peer->open_out + peer->update_out
|
||||
+ peer->keepalive_out
|
||||
+ peer->notify_out
|
||||
+ peer->refresh_out
|
||||
+ peer->dynamic_cap_out);
|
||||
json, "ribMemory",
|
||||
ents * sizeof(struct bgp_node));
|
||||
|
||||
json_object_int_add(json_peer, "tableVersion",
|
||||
peer->version[afi][safi]);
|
||||
json_object_int_add(json_peer, "outq",
|
||||
peer->obuf->count);
|
||||
json_object_int_add(json_peer, "inq", 0);
|
||||
peer_uptime(peer->uptime, timebuf,
|
||||
BGP_UPTIME_LEN, use_json,
|
||||
json_peer);
|
||||
ents = listcount(bgp->peer);
|
||||
json_object_int_add(json, "peerCount",
|
||||
ents);
|
||||
json_object_int_add(
|
||||
json_peer, "prefixReceivedCount",
|
||||
peer->pcount[afi][pfx_rcd_safi]);
|
||||
json, "peerMemory",
|
||||
ents * sizeof(struct peer));
|
||||
|
||||
if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN))
|
||||
json_object_string_add(json_peer,
|
||||
"state",
|
||||
"Idle (Admin)");
|
||||
else if (CHECK_FLAG(
|
||||
peer->sflags,
|
||||
PEER_STATUS_PREFIX_OVERFLOW))
|
||||
json_object_string_add(json_peer,
|
||||
"state",
|
||||
"Idle (PfxCt)");
|
||||
else
|
||||
json_object_string_add(
|
||||
json_peer, "state",
|
||||
lookup_msg(bgp_status_msg,
|
||||
peer->status, NULL));
|
||||
if ((ents = listcount(bgp->group))) {
|
||||
json_object_int_add(
|
||||
json, "peerGroupCount",
|
||||
ents);
|
||||
json_object_int_add(
|
||||
json, "peerGroupMemory",
|
||||
ents * sizeof(struct
|
||||
peer_group));
|
||||
}
|
||||
|
||||
if (peer->conf_if)
|
||||
json_object_string_add(json_peer,
|
||||
"idType",
|
||||
"interface");
|
||||
else if (peer->su.sa.sa_family == AF_INET)
|
||||
json_object_string_add(
|
||||
json_peer, "idType", "ipv4");
|
||||
else if (peer->su.sa.sa_family == AF_INET6)
|
||||
json_object_string_add(
|
||||
json_peer, "idType", "ipv6");
|
||||
|
||||
json_object_object_add(json_peers, peer->host,
|
||||
json_peer);
|
||||
if (CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||
BGP_CONFIG_DAMPENING))
|
||||
json_object_boolean_true_add(
|
||||
json,
|
||||
"dampeningEnabled");
|
||||
} else {
|
||||
memset(dn_flag, '\0', sizeof(dn_flag));
|
||||
if (peer_dynamic_neighbor(peer)) {
|
||||
dn_count++;
|
||||
dn_flag[0] = '*';
|
||||
}
|
||||
if (bgp_maxmed_onstartup_configured(bgp)
|
||||
&& bgp->maxmed_active)
|
||||
vty_out(vty,
|
||||
"Max-med on-startup active\n");
|
||||
if (bgp->v_maxmed_admin)
|
||||
vty_out(vty,
|
||||
"Max-med administrative active\n");
|
||||
|
||||
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);
|
||||
vty_out(vty,
|
||||
"BGP table version %" PRIu64
|
||||
"\n",
|
||||
bgp_table_version(
|
||||
bgp->rib[afi][safi]));
|
||||
|
||||
/* pad the neighbor column with spaces */
|
||||
if (len < max_neighbor_width)
|
||||
vty_out(vty, "%*s",
|
||||
max_neighbor_width - len, " ");
|
||||
ents = bgp_table_count(
|
||||
bgp->rib[afi][safi]);
|
||||
vty_out(vty,
|
||||
"RIB entries %ld, using %s of memory\n",
|
||||
ents,
|
||||
mtype_memstr(
|
||||
memstrbuf,
|
||||
sizeof(memstrbuf),
|
||||
ents * sizeof(struct
|
||||
bgp_node)));
|
||||
|
||||
vty_out(vty, "4 %10u %7d %7d %8" PRIu64
|
||||
" %4d %4zd %8s",
|
||||
peer->as,
|
||||
peer->open_in + peer->update_in
|
||||
+ peer->keepalive_in
|
||||
+ peer->notify_in
|
||||
+ peer->refresh_in
|
||||
+ peer->dynamic_cap_in,
|
||||
peer->open_out + peer->update_out
|
||||
+ peer->keepalive_out
|
||||
+ peer->notify_out
|
||||
+ peer->refresh_out
|
||||
+ peer->dynamic_cap_out,
|
||||
peer->version[afi][safi], 0,
|
||||
peer->obuf->count,
|
||||
peer_uptime(peer->uptime, timebuf,
|
||||
BGP_UPTIME_LEN, 0, NULL));
|
||||
/* Peer related usage */
|
||||
ents = listcount(bgp->peer);
|
||||
vty_out(vty,
|
||||
"Peers %ld, using %s of memory\n",
|
||||
ents,
|
||||
mtype_memstr(
|
||||
memstrbuf,
|
||||
sizeof(memstrbuf),
|
||||
ents * sizeof(struct
|
||||
peer)));
|
||||
|
||||
if (peer->status == Established)
|
||||
vty_out(vty, " %12ld",
|
||||
peer->pcount[afi]
|
||||
[pfx_rcd_safi]);
|
||||
else {
|
||||
if (CHECK_FLAG(peer->flags,
|
||||
PEER_FLAG_SHUTDOWN))
|
||||
vty_out(vty, " Idle (Admin)");
|
||||
else if (
|
||||
CHECK_FLAG(
|
||||
peer->sflags,
|
||||
PEER_STATUS_PREFIX_OVERFLOW))
|
||||
vty_out(vty, " Idle (PfxCt)");
|
||||
else
|
||||
vty_out(vty, " %12s",
|
||||
lookup_msg(
|
||||
bgp_status_msg,
|
||||
peer->status,
|
||||
NULL));
|
||||
}
|
||||
if ((ents = listcount(bgp->group)))
|
||||
vty_out(vty,
|
||||
"Peer groups %ld, using %s of memory\n",
|
||||
ents,
|
||||
mtype_memstr(
|
||||
memstrbuf,
|
||||
sizeof(memstrbuf),
|
||||
ents * sizeof(struct
|
||||
peer_group)));
|
||||
|
||||
if (CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||
BGP_CONFIG_DAMPENING))
|
||||
vty_out(vty,
|
||||
"Dampening enabled.\n");
|
||||
vty_out(vty, "\n");
|
||||
|
||||
/* Subtract 8 here because 'Neighbor' is
|
||||
* 8 characters */
|
||||
vty_out(vty, "Neighbor");
|
||||
vty_out(vty, "%*s",
|
||||
max_neighbor_width - 8, " ");
|
||||
vty_out(vty,
|
||||
"V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd\n");
|
||||
}
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
if (use_json) {
|
||||
json_peer = json_object_new_object();
|
||||
|
||||
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",
|
||||
peer->open_in + peer->update_in
|
||||
+ peer->keepalive_in
|
||||
+ peer->notify_in
|
||||
+ peer->refresh_in
|
||||
+ peer->dynamic_cap_in);
|
||||
json_object_int_add(
|
||||
json_peer, "msgSent",
|
||||
peer->open_out + peer->update_out
|
||||
+ peer->keepalive_out
|
||||
+ peer->notify_out
|
||||
+ peer->refresh_out
|
||||
+ peer->dynamic_cap_out);
|
||||
|
||||
json_object_int_add(json_peer, "tableVersion",
|
||||
peer->version[afi][safi]);
|
||||
json_object_int_add(json_peer, "outq",
|
||||
peer->obuf->count);
|
||||
json_object_int_add(json_peer, "inq", 0);
|
||||
peer_uptime(peer->uptime, timebuf,
|
||||
BGP_UPTIME_LEN, use_json,
|
||||
json_peer);
|
||||
json_object_int_add(
|
||||
json_peer, "prefixReceivedCount",
|
||||
peer->pcount[afi][pfx_rcd_safi]);
|
||||
|
||||
if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN))
|
||||
json_object_string_add(json_peer,
|
||||
"state",
|
||||
"Idle (Admin)");
|
||||
else if (CHECK_FLAG(
|
||||
peer->sflags,
|
||||
PEER_STATUS_PREFIX_OVERFLOW))
|
||||
json_object_string_add(json_peer,
|
||||
"state",
|
||||
"Idle (PfxCt)");
|
||||
else
|
||||
json_object_string_add(
|
||||
json_peer, "state",
|
||||
lookup_msg(bgp_status_msg,
|
||||
peer->status, NULL));
|
||||
|
||||
if (peer->conf_if)
|
||||
json_object_string_add(json_peer,
|
||||
"idType",
|
||||
"interface");
|
||||
else if (peer->su.sa.sa_family == AF_INET)
|
||||
json_object_string_add(
|
||||
json_peer, "idType", "ipv4");
|
||||
else if (peer->su.sa.sa_family == AF_INET6)
|
||||
json_object_string_add(
|
||||
json_peer, "idType", "ipv6");
|
||||
|
||||
json_object_object_add(json_peers, peer->host,
|
||||
json_peer);
|
||||
} else {
|
||||
memset(dn_flag, '\0', sizeof(dn_flag));
|
||||
if (peer_dynamic_neighbor(peer)) {
|
||||
dn_count++;
|
||||
dn_flag[0] = '*';
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* pad the neighbor column with spaces */
|
||||
if (len < max_neighbor_width)
|
||||
vty_out(vty, "%*s",
|
||||
max_neighbor_width - len, " ");
|
||||
|
||||
vty_out(vty, "4 %10u %7d %7d %8" PRIu64
|
||||
" %4d %4zd %8s",
|
||||
peer->as,
|
||||
peer->open_in + peer->update_in
|
||||
+ peer->keepalive_in
|
||||
+ peer->notify_in
|
||||
+ peer->refresh_in
|
||||
+ peer->dynamic_cap_in,
|
||||
peer->open_out + peer->update_out
|
||||
+ peer->keepalive_out
|
||||
+ peer->notify_out
|
||||
+ peer->refresh_out
|
||||
+ peer->dynamic_cap_out,
|
||||
peer->version[afi][safi], 0,
|
||||
peer->obuf->count,
|
||||
peer_uptime(peer->uptime, timebuf,
|
||||
BGP_UPTIME_LEN, 0, NULL));
|
||||
|
||||
if (peer->status == Established)
|
||||
vty_out(vty, " %12ld",
|
||||
peer->pcount[afi]
|
||||
[pfx_rcd_safi]);
|
||||
else {
|
||||
if (CHECK_FLAG(peer->flags,
|
||||
PEER_FLAG_SHUTDOWN))
|
||||
vty_out(vty, " Idle (Admin)");
|
||||
else if (
|
||||
CHECK_FLAG(
|
||||
peer->sflags,
|
||||
PEER_STATUS_PREFIX_OVERFLOW))
|
||||
vty_out(vty, " Idle (PfxCt)");
|
||||
else
|
||||
vty_out(vty, " %12s",
|
||||
lookup_msg(
|
||||
bgp_status_msg,
|
||||
peer->status,
|
||||
NULL));
|
||||
}
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (use_json) {
|
||||
@ -11156,14 +11145,14 @@ DEFUN (no_bgp_redistribute_ipv6,
|
||||
return bgp_redistribute_unset(bgp, AFI_IP6, type, 0);
|
||||
}
|
||||
|
||||
int bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
safi_t safi, int *write)
|
||||
void bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
safi_t safi)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Unicast redistribution only. */
|
||||
if (safi != SAFI_UNICAST)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
||||
/* Redistribute BGP does not make sense. */
|
||||
@ -11177,11 +11166,6 @@ int bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
continue;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
|
||||
/* Display "address-family" when it is not yet
|
||||
* diplayed. */
|
||||
bgp_config_write_family_header(vty, afi, safi,
|
||||
write);
|
||||
|
||||
/* "redistribute" configuration. */
|
||||
vty_out(vty, " redistribute %s",
|
||||
zebra_route_string(i));
|
||||
@ -11197,7 +11181,6 @@ int bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
}
|
||||
}
|
||||
}
|
||||
return *write;
|
||||
}
|
||||
|
||||
/* BGP node structure. */
|
||||
|
@ -46,10 +46,10 @@ struct bgp;
|
||||
extern void bgp_vty_init(void);
|
||||
extern const char *afi_safi_print(afi_t, safi_t);
|
||||
extern const char *afi_safi_json(afi_t, safi_t);
|
||||
extern int bgp_config_write_update_delay(struct vty *, struct bgp *);
|
||||
extern int bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp);
|
||||
extern int bgp_config_write_listen(struct vty *vty, struct bgp *bgp);
|
||||
extern int bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp);
|
||||
extern void bgp_config_write_update_delay(struct vty *, struct bgp *);
|
||||
extern void bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp);
|
||||
extern void bgp_config_write_listen(struct vty *vty, struct bgp *bgp);
|
||||
extern void bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp);
|
||||
extern int bgp_vty_return(struct vty *vty, int ret);
|
||||
extern struct peer *peer_and_group_lookup_vty(struct vty *vty,
|
||||
const char *peer_str);
|
||||
|
@ -26,10 +26,10 @@
|
||||
extern void bgp_zebra_init(struct thread_master *master);
|
||||
extern void bgp_zebra_destroy(void);
|
||||
extern int bgp_if_update_all(void);
|
||||
extern int bgp_config_write_maxpaths(struct vty *, struct bgp *, afi_t, safi_t,
|
||||
int *);
|
||||
extern int bgp_config_write_redistribute(struct vty *, struct bgp *, afi_t,
|
||||
safi_t, int *);
|
||||
extern void bgp_config_write_maxpaths(struct vty *, struct bgp *, afi_t,
|
||||
safi_t);
|
||||
extern void bgp_config_write_redistribute(struct vty *, struct bgp *, afi_t,
|
||||
safi_t);
|
||||
extern void bgp_zebra_announce(struct bgp_node *, struct prefix *,
|
||||
struct bgp_info *, struct bgp *, afi_t, safi_t);
|
||||
extern void bgp_zebra_announce_table(struct bgp *, afi_t, safi_t);
|
||||
|
346
bgpd/bgpd.c
346
bgpd/bgpd.c
@ -6204,14 +6204,8 @@ char *peer_uptime(time_t uptime2, char *buf, size_t len, u_char use_json,
|
||||
return buf;
|
||||
}
|
||||
|
||||
#define afi_header_vty_out(vty, afi, safi, write, format, ...) \
|
||||
do { \
|
||||
bgp_config_write_family_header(vty, afi, safi, write); \
|
||||
vty_out(vty, format, ## __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
|
||||
afi_t afi, safi_t safi, int *write)
|
||||
afi_t afi, safi_t safi)
|
||||
{
|
||||
struct bgp_filter *filter;
|
||||
struct bgp_filter *gfilter = NULL;
|
||||
@ -6230,16 +6224,13 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
|
||||
if (!gfilter || !gfilter->dlist[in].name
|
||||
|| strcmp(filter->dlist[in].name, gfilter->dlist[in].name)
|
||||
!= 0) {
|
||||
afi_header_vty_out(
|
||||
vty, afi, safi, write,
|
||||
" neighbor %s distribute-list %s in\n", addr,
|
||||
filter->dlist[in].name);
|
||||
vty_out(vty, " neighbor %s distribute-list %s in\n",
|
||||
addr, filter->dlist[in].name);
|
||||
}
|
||||
|
||||
if (filter->dlist[out].name && !gfilter) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s distribute-list %s out\n",
|
||||
addr, filter->dlist[out].name);
|
||||
vty_out(vty, " neighbor %s distribute-list %s out\n", addr,
|
||||
filter->dlist[out].name);
|
||||
}
|
||||
|
||||
/* prefix-list. */
|
||||
@ -6247,19 +6238,17 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
|
||||
if (!gfilter || !gfilter->plist[in].name
|
||||
|| strcmp(filter->plist[in].name, gfilter->plist[in].name)
|
||||
!= 0) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s prefix-list %s in\n",
|
||||
addr, filter->plist[in].name);
|
||||
vty_out(vty, " neighbor %s prefix-list %s in\n", addr,
|
||||
filter->plist[in].name);
|
||||
}
|
||||
|
||||
if (filter->plist[out].name)
|
||||
if (!gfilter || !gfilter->plist[out].name
|
||||
|| strcmp(filter->plist[out].name, gfilter->plist[out].name)
|
||||
!= 0) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s prefix-list %s out\n",
|
||||
addr, filter->plist[out].name);
|
||||
}
|
||||
if (filter->plist[out].name)
|
||||
if (!gfilter || !gfilter->plist[out].name
|
||||
|| strcmp(filter->plist[out].name, gfilter->plist[out].name)
|
||||
!= 0) {
|
||||
vty_out(vty, " neighbor %s prefix-list %s out\n", addr,
|
||||
filter->plist[out].name);
|
||||
}
|
||||
|
||||
/* route-map. */
|
||||
if (filter->map[RMAP_IN].name)
|
||||
@ -6267,9 +6256,8 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
|
||||
|| strcmp(filter->map[RMAP_IN].name,
|
||||
gfilter->map[RMAP_IN].name)
|
||||
!= 0) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s route-map %s in\n",
|
||||
addr, filter->map[RMAP_IN].name);
|
||||
vty_out(vty, " neighbor %s route-map %s in\n", addr,
|
||||
filter->map[RMAP_IN].name);
|
||||
}
|
||||
|
||||
if (filter->map[RMAP_OUT].name)
|
||||
@ -6277,16 +6265,14 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
|
||||
|| strcmp(filter->map[RMAP_OUT].name,
|
||||
gfilter->map[RMAP_OUT].name)
|
||||
!= 0) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s route-map %s out\n",
|
||||
addr, filter->map[RMAP_OUT].name);
|
||||
vty_out(vty, " neighbor %s route-map %s out\n", addr,
|
||||
filter->map[RMAP_OUT].name);
|
||||
}
|
||||
|
||||
/* unsuppress-map */
|
||||
if (filter->usmap.name && !gfilter) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s unsuppress-map %s\n", addr,
|
||||
filter->usmap.name);
|
||||
vty_out(vty, " neighbor %s unsuppress-map %s\n", addr,
|
||||
filter->usmap.name);
|
||||
}
|
||||
|
||||
/* filter-list. */
|
||||
@ -6294,15 +6280,13 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
|
||||
if (!gfilter || !gfilter->aslist[in].name
|
||||
|| strcmp(filter->aslist[in].name, gfilter->aslist[in].name)
|
||||
!= 0) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s filter-list %s in\n",
|
||||
addr, filter->aslist[in].name);
|
||||
vty_out(vty, " neighbor %s filter-list %s in\n", addr,
|
||||
filter->aslist[in].name);
|
||||
}
|
||||
|
||||
if (filter->aslist[out].name && !gfilter) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s filter-list %s out\n", addr,
|
||||
filter->aslist[out].name);
|
||||
vty_out(vty, " neighbor %s filter-list %s out\n", addr,
|
||||
filter->aslist[out].name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6622,8 +6606,7 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
|
||||
|
||||
/* BGP peer configuration display function. */
|
||||
static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
struct peer *peer, afi_t afi, safi_t safi,
|
||||
int *write)
|
||||
struct peer *peer, afi_t afi, safi_t safi)
|
||||
{
|
||||
struct peer *g_peer = NULL;
|
||||
char *addr;
|
||||
@ -6646,36 +6629,29 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
/* If the peer-group is active but peer is not, print a 'no
|
||||
* activate' */
|
||||
if (g_peer->afc[afi][safi] && !peer->afc[afi][safi]) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" no neighbor %s activate\n", addr);
|
||||
vty_out(vty, " no neighbor %s activate\n", addr);
|
||||
}
|
||||
|
||||
/* If the peer-group is not active but peer is, print an
|
||||
'activate' */
|
||||
else if (!g_peer->afc[afi][safi] && peer->afc[afi][safi]) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s activate\n", addr);
|
||||
vty_out(vty, " neighbor %s activate\n", addr);
|
||||
}
|
||||
} else {
|
||||
if (peer->afc[afi][safi]) {
|
||||
if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
|
||||
if (bgp_flag_check(bgp,
|
||||
BGP_FLAG_NO_DEFAULT_IPV4)) {
|
||||
afi_header_vty_out(
|
||||
vty, afi, safi, write,
|
||||
" neighbor %s activate\n",
|
||||
vty_out(vty, " neighbor %s activate\n",
|
||||
addr);
|
||||
}
|
||||
} else
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s activate\n",
|
||||
addr);
|
||||
vty_out(vty, " neighbor %s activate\n", addr);
|
||||
} else {
|
||||
if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
|
||||
if (!bgp_flag_check(bgp,
|
||||
BGP_FLAG_NO_DEFAULT_IPV4)) {
|
||||
afi_header_vty_out(
|
||||
vty, afi, safi, write,
|
||||
vty_out(vty,
|
||||
" no neighbor %s activate\n",
|
||||
addr);
|
||||
}
|
||||
@ -6686,25 +6662,20 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
/* addpath TX knobs */
|
||||
if (peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_ADDPATH_TX_ALL_PATHS)) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s addpath-tx-all-paths\n",
|
||||
addr);
|
||||
vty_out(vty, " neighbor %s addpath-tx-all-paths\n", addr);
|
||||
}
|
||||
|
||||
if (peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s addpath-tx-bestpath-per-AS\n",
|
||||
addr);
|
||||
vty_out(vty, " neighbor %s addpath-tx-bestpath-per-AS\n",
|
||||
addr);
|
||||
}
|
||||
|
||||
/* ORF capability. */
|
||||
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM)
|
||||
|| peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_ORF_PREFIX_RM)) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s capability orf prefix-list",
|
||||
addr);
|
||||
vty_out(vty, " neighbor %s capability orf prefix-list", addr);
|
||||
|
||||
if (peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_ORF_PREFIX_SM)
|
||||
@ -6722,57 +6693,46 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
/* Route reflector client. */
|
||||
if (peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_REFLECTOR_CLIENT)) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s route-reflector-client\n",
|
||||
addr);
|
||||
vty_out(vty, " neighbor %s route-reflector-client\n", addr);
|
||||
}
|
||||
|
||||
/* next-hop-self force */
|
||||
if (peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_FORCE_NEXTHOP_SELF)) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s next-hop-self force\n", addr);
|
||||
vty_out(vty, " neighbor %s next-hop-self force\n", addr);
|
||||
}
|
||||
|
||||
/* next-hop-self */
|
||||
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s next-hop-self\n", addr);
|
||||
vty_out(vty, " neighbor %s next-hop-self\n", addr);
|
||||
}
|
||||
|
||||
/* remove-private-AS */
|
||||
if (peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) {
|
||||
afi_header_vty_out(
|
||||
vty, afi, safi, write,
|
||||
" neighbor %s remove-private-AS all replace-AS\n",
|
||||
vty_out(vty, " neighbor %s remove-private-AS all replace-AS\n",
|
||||
addr);
|
||||
}
|
||||
|
||||
else if (peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) {
|
||||
afi_header_vty_out(
|
||||
vty, afi, safi, write,
|
||||
" neighbor %s remove-private-AS replace-AS\n", addr);
|
||||
vty_out(vty, " neighbor %s remove-private-AS replace-AS\n",
|
||||
addr);
|
||||
}
|
||||
|
||||
else if (peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s remove-private-AS all\n",
|
||||
addr);
|
||||
vty_out(vty, " neighbor %s remove-private-AS all\n", addr);
|
||||
}
|
||||
|
||||
else if (peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_REMOVE_PRIVATE_AS)) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s remove-private-AS\n", addr);
|
||||
vty_out(vty, " neighbor %s remove-private-AS\n", addr);
|
||||
}
|
||||
|
||||
/* as-override */
|
||||
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s as-override\n", addr);
|
||||
vty_out(vty, " neighbor %s as-override\n", addr);
|
||||
}
|
||||
|
||||
/* send-community print. */
|
||||
@ -6784,27 +6744,21 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
&& peergroup_af_flag_check(
|
||||
peer, afi, safi,
|
||||
PEER_FLAG_SEND_LARGE_COMMUNITY)) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s send-community all\n",
|
||||
addr);
|
||||
vty_out(vty, " neighbor %s send-community all\n",
|
||||
addr);
|
||||
} else if (peergroup_af_flag_check(
|
||||
peer, afi, safi,
|
||||
PEER_FLAG_SEND_LARGE_COMMUNITY)) {
|
||||
afi_header_vty_out(
|
||||
vty, afi, safi, write,
|
||||
" neighbor %s send-community large\n", addr);
|
||||
vty_out(vty, " neighbor %s send-community large\n",
|
||||
addr);
|
||||
} else if (peergroup_af_flag_check(
|
||||
peer, afi, safi,
|
||||
PEER_FLAG_SEND_EXT_COMMUNITY)) {
|
||||
afi_header_vty_out(
|
||||
vty, afi, safi, write,
|
||||
" neighbor %s send-community extended\n",
|
||||
vty_out(vty, " neighbor %s send-community extended\n",
|
||||
addr);
|
||||
} else if (peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_SEND_COMMUNITY)) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s send-community\n",
|
||||
addr);
|
||||
vty_out(vty, " neighbor %s send-community\n", addr);
|
||||
}
|
||||
} else {
|
||||
if (!peer_af_flag_check(peer, afi, safi,
|
||||
@ -6821,9 +6775,8 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
&& (!g_peer || peer_af_flag_check(
|
||||
g_peer, afi, safi,
|
||||
PEER_FLAG_SEND_LARGE_COMMUNITY))) {
|
||||
afi_header_vty_out(
|
||||
vty, afi, safi, write,
|
||||
" no neighbor %s send-community all\n", addr);
|
||||
vty_out(vty, " no neighbor %s send-community all\n",
|
||||
addr);
|
||||
} else {
|
||||
if (!peer_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_SEND_LARGE_COMMUNITY)
|
||||
@ -6831,8 +6784,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
|| peer_af_flag_check(
|
||||
g_peer, afi, safi,
|
||||
PEER_FLAG_SEND_LARGE_COMMUNITY))) {
|
||||
afi_header_vty_out(
|
||||
vty, afi, safi, write,
|
||||
vty_out(vty,
|
||||
" no neighbor %s send-community large\n",
|
||||
addr);
|
||||
}
|
||||
@ -6843,8 +6795,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
|| peer_af_flag_check(
|
||||
g_peer, afi, safi,
|
||||
PEER_FLAG_SEND_EXT_COMMUNITY))) {
|
||||
afi_header_vty_out(
|
||||
vty, afi, safi, write,
|
||||
vty_out(vty,
|
||||
" no neighbor %s send-community extended\n",
|
||||
addr);
|
||||
}
|
||||
@ -6854,8 +6805,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
&& (!g_peer || peer_af_flag_check(
|
||||
g_peer, afi, safi,
|
||||
PEER_FLAG_SEND_COMMUNITY))) {
|
||||
afi_header_vty_out(
|
||||
vty, afi, safi, write,
|
||||
vty_out(vty,
|
||||
" no neighbor %s send-community\n",
|
||||
addr);
|
||||
}
|
||||
@ -6873,8 +6823,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
|| (peer->default_rmap[afi][safi].name
|
||||
&& strcmp(peer->default_rmap[afi][safi].name,
|
||||
g_peer->default_rmap[afi][safi].name))))) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s default-originate", addr);
|
||||
vty_out(vty, " neighbor %s default-originate", addr);
|
||||
if (peer->default_rmap[afi][safi].name)
|
||||
vty_out(vty, " route-map %s",
|
||||
peer->default_rmap[afi][safi].name);
|
||||
@ -6883,9 +6832,8 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
|
||||
/* Soft reconfiguration inbound. */
|
||||
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_SOFT_RECONFIG)) {
|
||||
afi_header_vty_out(
|
||||
vty, afi, safi, write,
|
||||
" neighbor %s soft-reconfiguration inbound\n", addr);
|
||||
vty_out(vty, " neighbor %s soft-reconfiguration inbound\n",
|
||||
addr);
|
||||
}
|
||||
|
||||
/* maximum-prefix. */
|
||||
@ -6898,9 +6846,8 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
PEER_FLAG_MAX_PREFIX_WARNING)
|
||||
!= CHECK_FLAG(peer->af_flags[afi][safi],
|
||||
PEER_FLAG_MAX_PREFIX_WARNING)) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s maximum-prefix %lu",
|
||||
addr, peer->pmax[afi][safi]);
|
||||
vty_out(vty, " neighbor %s maximum-prefix %lu", addr,
|
||||
peer->pmax[afi][safi]);
|
||||
if (peer->pmax_threshold[afi][safi]
|
||||
!= MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
|
||||
vty_out(vty, " %u",
|
||||
@ -6917,16 +6864,13 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
/* Route server client. */
|
||||
if (peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_RSERVER_CLIENT)) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s route-server-client\n", addr);
|
||||
vty_out(vty, " neighbor %s route-server-client\n", addr);
|
||||
}
|
||||
|
||||
/* Nexthop-local unchanged. */
|
||||
if (peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s nexthop-local unchanged\n",
|
||||
addr);
|
||||
vty_out(vty, " neighbor %s nexthop-local unchanged\n", addr);
|
||||
}
|
||||
|
||||
/* allowas-in <1-10> */
|
||||
@ -6937,14 +6881,11 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
|| peer->allowas_in[afi][safi]
|
||||
!= g_peer->allowas_in[afi][safi]) {
|
||||
if (peer->allowas_in[afi][safi] == 3) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s allowas-in\n",
|
||||
addr);
|
||||
vty_out(vty, " neighbor %s allowas-in\n",
|
||||
addr);
|
||||
} else {
|
||||
afi_header_vty_out(
|
||||
vty, afi, safi, write,
|
||||
" neighbor %s allowas-in %d\n", addr,
|
||||
peer->allowas_in[afi][safi]);
|
||||
vty_out(vty, " neighbor %s allowas-in %d\n",
|
||||
addr, peer->allowas_in[afi][safi]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6955,9 +6896,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
if (!peer_group_active(peer)
|
||||
|| !peer_af_flag_check(g_peer, afi, safi,
|
||||
PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s allowas-in origin\n",
|
||||
addr);
|
||||
vty_out(vty, " neighbor %s allowas-in origin\n", addr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6967,15 +6906,13 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
|| !peer_af_flag_check(g_peer, afi, safi, PEER_FLAG_WEIGHT)
|
||||
|| peer->weight[afi][safi] != g_peer->weight[afi][safi]) {
|
||||
if (peer->weight[afi][safi]) {
|
||||
afi_header_vty_out(vty, afi, safi, write,
|
||||
" neighbor %s weight %lu\n",
|
||||
addr,
|
||||
peer->weight[afi][safi]);
|
||||
vty_out(vty, " neighbor %s weight %lu\n", addr,
|
||||
peer->weight[afi][safi]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Filter. */
|
||||
bgp_config_write_filter(vty, peer, afi, safi, write);
|
||||
bgp_config_write_filter(vty, peer, afi, safi);
|
||||
|
||||
/* atribute-unchanged. */
|
||||
if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) ||
|
||||
@ -6990,8 +6927,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
peergroup_af_flag_check(peer, afi, safi,
|
||||
PEER_FLAG_MED_UNCHANGED)) {
|
||||
|
||||
afi_header_vty_out(
|
||||
vty, afi, safi, write,
|
||||
vty_out(vty,
|
||||
" neighbor %s attribute-unchanged%s%s%s\n",
|
||||
addr,
|
||||
peer_af_flag_check(
|
||||
@ -7012,64 +6948,52 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||
}
|
||||
}
|
||||
|
||||
/* Display "address-family" configuration header. */
|
||||
void bgp_config_write_family_header(struct vty *vty, afi_t afi, safi_t safi,
|
||||
int *write)
|
||||
{
|
||||
if (*write)
|
||||
return;
|
||||
|
||||
vty_out(vty, " !\n address-family ");
|
||||
|
||||
if (afi == AFI_IP) {
|
||||
if (safi == SAFI_UNICAST)
|
||||
vty_out(vty, "ipv4 unicast");
|
||||
else if (safi == SAFI_LABELED_UNICAST)
|
||||
vty_out(vty, "ipv4 labeled-unicast");
|
||||
else if (safi == SAFI_MULTICAST)
|
||||
vty_out(vty, "ipv4 multicast");
|
||||
else if (safi == SAFI_MPLS_VPN)
|
||||
vty_out(vty, "ipv4 vpn");
|
||||
else if (safi == SAFI_ENCAP)
|
||||
vty_out(vty, "ipv4 encap");
|
||||
} else if (afi == AFI_IP6) {
|
||||
if (safi == SAFI_UNICAST)
|
||||
vty_out(vty, "ipv6 unicast");
|
||||
else if (safi == SAFI_LABELED_UNICAST)
|
||||
vty_out(vty, "ipv6 labeled-unicast");
|
||||
else if (safi == SAFI_MULTICAST)
|
||||
vty_out(vty, "ipv6 multicast");
|
||||
else if (safi == SAFI_MPLS_VPN)
|
||||
vty_out(vty, "ipv6 vpn");
|
||||
else if (safi == SAFI_ENCAP)
|
||||
vty_out(vty, "ipv6 encap");
|
||||
} else if (afi == AFI_L2VPN) {
|
||||
if (safi == SAFI_EVPN)
|
||||
vty_out(vty, "l2vpn evpn");
|
||||
}
|
||||
vty_out(vty, "\n");
|
||||
|
||||
*write = 1;
|
||||
}
|
||||
|
||||
/* Address family based peer configuration display. */
|
||||
static int bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
safi_t safi)
|
||||
static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
safi_t safi)
|
||||
{
|
||||
int write = 0;
|
||||
struct peer *peer;
|
||||
struct peer_group *group;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
bgp_config_write_distance(vty, bgp, afi, safi, &write);
|
||||
|
||||
bgp_config_write_network(vty, bgp, afi, safi, &write);
|
||||
vty_frame(vty, " !\n address-family ");
|
||||
if (afi == AFI_IP) {
|
||||
if (safi == SAFI_UNICAST)
|
||||
vty_frame(vty, "ipv4 unicast");
|
||||
else if (safi == SAFI_LABELED_UNICAST)
|
||||
vty_frame(vty, "ipv4 labeled-unicast");
|
||||
else if (safi == SAFI_MULTICAST)
|
||||
vty_frame(vty, "ipv4 multicast");
|
||||
else if (safi == SAFI_MPLS_VPN)
|
||||
vty_frame(vty, "ipv4 vpn");
|
||||
else if (safi == SAFI_ENCAP)
|
||||
vty_frame(vty, "ipv4 encap");
|
||||
} else if (afi == AFI_IP6) {
|
||||
if (safi == SAFI_UNICAST)
|
||||
vty_frame(vty, "ipv6 unicast");
|
||||
else if (safi == SAFI_LABELED_UNICAST)
|
||||
vty_frame(vty, "ipv6 labeled-unicast");
|
||||
else if (safi == SAFI_MULTICAST)
|
||||
vty_frame(vty, "ipv6 multicast");
|
||||
else if (safi == SAFI_MPLS_VPN)
|
||||
vty_frame(vty, "ipv6 vpn");
|
||||
else if (safi == SAFI_ENCAP)
|
||||
vty_frame(vty, "ipv6 encap");
|
||||
} else if (afi == AFI_L2VPN) {
|
||||
if (safi == SAFI_EVPN)
|
||||
vty_frame(vty, "l2vpn evpn");
|
||||
}
|
||||
vty_frame(vty, "\n");
|
||||
|
||||
bgp_config_write_redistribute(vty, bgp, afi, safi, &write);
|
||||
bgp_config_write_distance(vty, bgp, afi, safi);
|
||||
|
||||
bgp_config_write_network(vty, bgp, afi, safi);
|
||||
|
||||
bgp_config_write_redistribute(vty, bgp, afi, safi);
|
||||
|
||||
for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
|
||||
bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi,
|
||||
&write);
|
||||
bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi);
|
||||
|
||||
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
|
||||
/* Skip dynamic neighbors. */
|
||||
@ -7078,20 +7002,16 @@ static int bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
|
||||
/* Do not display doppelganger peers */
|
||||
if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
|
||||
bgp_config_write_peer_af(vty, bgp, peer, afi, safi,
|
||||
&write);
|
||||
bgp_config_write_peer_af(vty, bgp, peer, afi, safi);
|
||||
}
|
||||
|
||||
bgp_config_write_maxpaths(vty, bgp, afi, safi, &write);
|
||||
bgp_config_write_table_map(vty, bgp, afi, safi, &write);
|
||||
bgp_config_write_maxpaths(vty, bgp, afi, safi);
|
||||
bgp_config_write_table_map(vty, bgp, afi, safi);
|
||||
|
||||
if (safi == SAFI_EVPN)
|
||||
bgp_config_write_evpn_info(vty, bgp, afi, safi, &write);
|
||||
bgp_config_write_evpn_info(vty, bgp, afi, safi);
|
||||
|
||||
if (write)
|
||||
vty_out(vty, " exit-address-family\n");
|
||||
|
||||
return write;
|
||||
vty_endframe(vty, " exit-address-family\n");
|
||||
}
|
||||
|
||||
int bgp_config_write(struct vty *vty)
|
||||
@ -7119,11 +7039,11 @@ int bgp_config_write(struct vty *vty)
|
||||
vty_out(vty, "bgp route-map delay-timer %u\n",
|
||||
bm->rmap_update_timer);
|
||||
|
||||
if (write)
|
||||
vty_out(vty, "!\n");
|
||||
|
||||
/* BGP configuration. */
|
||||
for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
|
||||
if (write)
|
||||
vty_out(vty, "!\n");
|
||||
|
||||
/* Router bgp ASN */
|
||||
vty_out(vty, "router bgp %u", bgp->as);
|
||||
|
||||
@ -7343,54 +7263,46 @@ int bgp_config_write(struct vty *vty)
|
||||
vty_out(vty, " no auto-summary\n");
|
||||
|
||||
/* IPv4 unicast configuration. */
|
||||
write +=
|
||||
bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST);
|
||||
bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST);
|
||||
|
||||
/* IPv4 multicast configuration. */
|
||||
write += bgp_config_write_family(vty, bgp, AFI_IP,
|
||||
SAFI_MULTICAST);
|
||||
bgp_config_write_family(vty, bgp, AFI_IP, SAFI_MULTICAST);
|
||||
|
||||
/* IPv4 labeled-unicast configuration. */
|
||||
write += bgp_config_write_family(vty, bgp, AFI_IP,
|
||||
SAFI_LABELED_UNICAST);
|
||||
bgp_config_write_family(vty, bgp, AFI_IP, SAFI_LABELED_UNICAST);
|
||||
|
||||
/* IPv4 VPN configuration. */
|
||||
write += bgp_config_write_family(vty, bgp, AFI_IP,
|
||||
SAFI_MPLS_VPN);
|
||||
bgp_config_write_family(vty, bgp, AFI_IP, SAFI_MPLS_VPN);
|
||||
|
||||
/* ENCAPv4 configuration. */
|
||||
write += bgp_config_write_family(vty, bgp, AFI_IP, SAFI_ENCAP);
|
||||
bgp_config_write_family(vty, bgp, AFI_IP, SAFI_ENCAP);
|
||||
|
||||
/* IPv6 unicast configuration. */
|
||||
write += bgp_config_write_family(vty, bgp, AFI_IP6,
|
||||
SAFI_UNICAST);
|
||||
bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_UNICAST);
|
||||
|
||||
/* IPv6 multicast configuration. */
|
||||
write += bgp_config_write_family(vty, bgp, AFI_IP6,
|
||||
SAFI_MULTICAST);
|
||||
bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_MULTICAST);
|
||||
|
||||
/* IPv6 labeled-unicast configuration. */
|
||||
write += bgp_config_write_family(vty, bgp, AFI_IP6,
|
||||
SAFI_LABELED_UNICAST);
|
||||
bgp_config_write_family(vty, bgp, AFI_IP6,
|
||||
SAFI_LABELED_UNICAST);
|
||||
|
||||
/* IPv6 VPN configuration. */
|
||||
write += bgp_config_write_family(vty, bgp, AFI_IP6,
|
||||
SAFI_MPLS_VPN);
|
||||
bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
|
||||
|
||||
/* ENCAPv6 configuration. */
|
||||
write += bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_ENCAP);
|
||||
bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_ENCAP);
|
||||
|
||||
/* EVPN configuration. */
|
||||
write +=
|
||||
bgp_config_write_family(vty, bgp, AFI_L2VPN, SAFI_EVPN);
|
||||
bgp_config_write_family(vty, bgp, AFI_L2VPN, SAFI_EVPN);
|
||||
|
||||
#if ENABLE_BGP_VNC
|
||||
write += bgp_rfapi_cfg_write(vty, bgp);
|
||||
bgp_rfapi_cfg_write(vty, bgp);
|
||||
#endif
|
||||
|
||||
write++;
|
||||
vty_out(vty, "!\n");
|
||||
}
|
||||
return write;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bgp_master_init(struct thread_master *master)
|
||||
|
@ -1238,7 +1238,6 @@ extern void peer_xfer_config(struct peer *dst, struct peer *src);
|
||||
extern char *peer_uptime(time_t, char *, size_t, u_char, json_object *);
|
||||
|
||||
extern int bgp_config_write(struct vty *);
|
||||
extern void bgp_config_write_family_header(struct vty *, afi_t, safi_t, int *);
|
||||
|
||||
extern void bgp_master_init(struct thread_master *master);
|
||||
|
||||
|
@ -1837,6 +1837,7 @@ AC_CONFIG_FILES([Makefile
|
||||
doc/watchfrr.8
|
||||
doc/zebra.8
|
||||
doc/frr.1
|
||||
doc/frr-args.8
|
||||
pkgsrc/bgpd.sh pkgsrc/ospf6d.sh pkgsrc/ospfd.sh
|
||||
pkgsrc/ripd.sh pkgsrc/ripngd.sh pkgsrc/zebra.sh
|
||||
pkgsrc/eigrpd.sh])
|
||||
|
1
debian/frr.install
vendored
1
debian/frr.install
vendored
@ -16,6 +16,7 @@ usr/share/man/man8/ripngd.8
|
||||
usr/share/man/man8/zebra.8
|
||||
usr/share/man/man8/isisd.8
|
||||
usr/share/man/man8/watchfrr.8
|
||||
usr/share/man/man8/frr-args.8
|
||||
usr/share/snmp/mibs/
|
||||
tools/etc/* etc/
|
||||
tools/*.service lib/systemd/system
|
||||
|
@ -79,7 +79,7 @@ frr_TEXINFOS = appendix.texi basic.texi bgpd.texi isisd.texi filter.texi \
|
||||
.dia.png:
|
||||
$(DIATOPNG) "$@" $<
|
||||
|
||||
man_MANS = frr.1
|
||||
man_MANS = frr.1 frr-args.8
|
||||
|
||||
if PIMD
|
||||
man_MANS += pimd.8
|
||||
|
248
doc/frr-args.8.in
Normal file
248
doc/frr-args.8.in
Normal file
@ -0,0 +1,248 @@
|
||||
.TH frr-args 8 "28 August 2017" "@PACKAGE_FULLNAME@ general options" "Version @PACKAGE_VERSION@"
|
||||
.SH NAME
|
||||
frr-args \- common command line options for all @PACKAGE_FULLNAME@ daemons.
|
||||
.SH SYNOPSIS
|
||||
<\fBzebra\fR|\fBbgpd\fR|\fB...\fR>
|
||||
[\fB\-h\fR] [\fB\-v\fR]
|
||||
|
||||
<\fBzebra\fR|\fBbgpd\fR|\fB...\fR>
|
||||
[\fB\-d\fR|\fB\-t\fR|\fB\-dt\fR]
|
||||
[\fB\-C\fR]
|
||||
[\fB\-f\fR \fIconfig-file\fR]
|
||||
[\fB\-i\fR \fIpid-file\fR]
|
||||
[\fB\-z\fR \fIzclient-path\fR]
|
||||
[\fB\-u\fR \fIuser\fR]
|
||||
[\fB\-g\fR \fIgroup\fR]
|
||||
[\fB\-A\fR \fIvty-addr\fR]
|
||||
[\fB\-P\fR \fIvty-port\fR]
|
||||
[\fB\-M\fR \fImodule\fR[\fB:\fIoptions\fR]]
|
||||
[\fB\-N\fR \fIpathspace\fR]
|
||||
[\fB\-\-vty_socket\fR \fIvty-path\fR]
|
||||
[\fB\-\-moduledir\fR \fImodule-path\fR]
|
||||
|
||||
.SH DESCRIPTION
|
||||
@PACKAGE_NAME@ daemons share a large part of their command line options;
|
||||
this man page documents these. For options on specific daemons please refer
|
||||
to their respective man pages. Most of the common options are related to
|
||||
process control, configuration and common library functionality.
|
||||
|
||||
.SH HELP AND VERSION
|
||||
.TP
|
||||
\fB\-h\fR, \fB\-\-help\fR
|
||||
Print a short description of the daemon's command line options.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Print version and build information for the daemon.
|
||||
.PP
|
||||
Both of these options inhibit normal operation and will immediately exit.
|
||||
|
||||
.SH PROCESS CONTROL
|
||||
These options control background operation:
|
||||
.TP
|
||||
\fB\-d\fR, \fB\-\-daemon\fR
|
||||
Launches the process in background/daemon mode, forking and detaching from
|
||||
the terminal.
|
||||
|
||||
The parent process will delay its exit until the daemon/child has finished
|
||||
its initialization and has entered its main loop. This is important for
|
||||
\fBzebra\fR startup because the other daemons will attempt to connect to
|
||||
\fBzebra\fR. A return from \fBzebra -d\fR guarantees its readiness to
|
||||
accept these connections.
|
||||
.TP
|
||||
\fB\-t\fR, \fB\-\-terminal\fR
|
||||
Opens an interactive VTY session on the terminal, allowing for both state
|
||||
and configuration operations. Note that the terminal starts operating after
|
||||
startup has completed and the configuration file has been loaded.
|
||||
|
||||
The process will exit when end of file is detected on the terminal. It is
|
||||
possible to daemonize a process started with \fB-t\fR (but without \fB-d\fR)
|
||||
by sending \fISIGQUIT\fR to the process (normally mapped to a \fI^\\\fR
|
||||
keypress.)
|
||||
.TP
|
||||
\fB\-dt\fR, \fB\-\-daemon \-\-terminal\fR
|
||||
This combination of the previous two options will delay the daemon from
|
||||
going into background until the terminal session ends (by end of file.)
|
||||
|
||||
If the process receives \fISIGINT\fR (e.g. a \fI^C\fR keypress) in this
|
||||
mode, it will exit instead of daemonizing.
|
||||
.PP
|
||||
It is safe to suspend (\fISIGTSTP\fR / \fI^Z\fR) the terminal session
|
||||
opened by the previous two options; this will only stop the terminal but
|
||||
not the protocol daemon itself (which runs in a separate second process.)
|
||||
|
||||
.SH CONFIGURATION AND PATHS
|
||||
The following options control configuration and file system locations for
|
||||
@PACKAGE_NAME@ processes:
|
||||
.TP
|
||||
\fB\-f\fR, \fB\-\-config_file\fR \fIconfig-file\fR
|
||||
Specify a configuration file to be used instead of the default
|
||||
\fB\fI@CFG_SYSCONF@/<daemon>.conf\fR file.
|
||||
|
||||
Note that the daemon will attempt to write to this file if the
|
||||
\fIwrite file\fR command is issued on its VTY interface or through
|
||||
\fBvtysh\fR.
|
||||
.TP
|
||||
\fB\-C\fR, \fB\-\-dryrun\fR
|
||||
Load the configuration file and check its validity, then exit.
|
||||
.TP
|
||||
\fB\-i\fR, \fB\-\-pid_file\fR \fIpid-file\fR
|
||||
Output a pid file to a location other than the default
|
||||
\fB\fI@CFG_STATE@/<daemon>.pid\fR.
|
||||
.TP
|
||||
\fB\-z\fR, \fB\-\-socket\fR \fIzclient-path\fR
|
||||
Override the path of the ZAPI socket used to communicate between \fBzebra\fR
|
||||
and the various protocol daemons. The default is
|
||||
\fB\fI@CFG_STATE@/zserv.api\fR. The value of this option must be the same
|
||||
across all daemons.
|
||||
.TP
|
||||
\fB\-N\fR, \fB\-\-pathspace\fR \fIpathspace\fR
|
||||
Insert \fIpathspace\fR into all default paths, changing the defaults to:
|
||||
.IP
|
||||
\fB@CFG_SYSCONF@/\fIpathspace\fB/<daemon>.conf\fR
|
||||
.br
|
||||
\fB@CFG_STATE@/\fIpathspace\fB/<daemon>.pid\fR
|
||||
.br
|
||||
\fB@CFG_STATE@/\fIpathspace\fB/<daemon>.vty\fR
|
||||
.br
|
||||
\fB@CFG_STATE@/\fIpathspace\fB/zserv.api\fR
|
||||
|
||||
\'.\' and \'/\' characters will not be accepted in \fIpathspace\fR, but the
|
||||
empty string will be accepted.
|
||||
|
||||
Note that this only changes the respective defaults, it has no effect on
|
||||
the respective path if the \fB\-f\fR, \fB\-i\fR, \fB\-z\fR or
|
||||
\fB\-\-vty_socket\fR options are used.
|
||||
|
||||
The purpose of this option is to easily group all file system related
|
||||
bits together for running multiple fully-separate "logical routers" on a
|
||||
system, particularly with Linux network namespaces. Groups of daemons
|
||||
running with distinct \fIpathspace\fR values will be completely unaware
|
||||
of each other and not interact in any way.
|
||||
|
||||
This option does not do any system setup (like network namespaces.) This
|
||||
must be done by the user, for example by running:
|
||||
.IP
|
||||
\fBip netns exec \fInamespace \fB<daemon> -N \fInamespace\fR
|
||||
|
||||
.SH PROCESS CREDENTIALS
|
||||
.TP
|
||||
\fB\-u\fR, \fB\-\-user\fR \fIuser\fR
|
||||
(default: \fB@enable_user@\fR)
|
||||
.TP
|
||||
\fB\-g\fR, \fB\-\-group\fR \fIgroup\fR
|
||||
(default: \fB@enable_group@\fR)
|
||||
.IP
|
||||
Change the user/group which the daemon will switch to.
|
||||
.PP
|
||||
Note that there is an additional group, \fB@enable_vty_group@\fR, which
|
||||
controls group ownership of the VTY sockets. The name of this group cannot
|
||||
currently be changed, and \fIuser\fR must be a member of this group.
|
||||
|
||||
.SH VTY SETUP
|
||||
These following options control the daemon's VTY (interactive command line)
|
||||
interface. The interface is available over TCP, using the telnet protocol,
|
||||
as well as through the \fBvtysh\fR frontend.
|
||||
.TP
|
||||
\fB\-A\fR, \fB--vty_addr\fR \fIvty-addr\fR
|
||||
Specify an IP/IPv6 address to bind the TCP VTY interface to. It is
|
||||
generally recommended to specify \fI::1\fR or \fI127.0.0.1\fR. For reasons
|
||||
of backwards compatibility, the default is to listen on all interfaces.
|
||||
.TP
|
||||
\fB\-P\fR, \fB--vty_port\fR \fIvty-port\fR
|
||||
Override the daemon's default TCP VTY port (each daemon has a different
|
||||
default value upwards of 2600, listed below.) Specifying \fI0\fR disables
|
||||
the TCP VTY interface.
|
||||
|
||||
Default ports are:
|
||||
|
||||
.ta 16m
|
||||
zebra 2601
|
||||
.br
|
||||
ripd 2602
|
||||
.br
|
||||
ripngd 2603
|
||||
.br
|
||||
ospfd 2604
|
||||
.br
|
||||
bgpd 2605
|
||||
.br
|
||||
ospf6d 2606
|
||||
.br
|
||||
isisd 2608
|
||||
.br
|
||||
babeld 2609
|
||||
.br
|
||||
nhrpd 2610
|
||||
.br
|
||||
pimd 2611
|
||||
.br
|
||||
ldpd 2612
|
||||
.br
|
||||
eigrpd 2613
|
||||
|
||||
Port 2607 is used for ospfd's Opaque LSA API, while port 2600 is used for
|
||||
the (insecure) TCP-ZEBRA interface.
|
||||
.TP
|
||||
\fB\-\-vty_socket\fR \fIvty-path\fR
|
||||
Overrides the directory used for the \fB<daemon>.vty\fR sockets.
|
||||
\fBvtysh\fR connects to these sockets in order to access each daemon's
|
||||
VTY.
|
||||
.br
|
||||
Default: \fB\fI@CFG_STATE@\fR[\fB/\fI<pathspace>\fR]
|
||||
|
||||
NB: Unlike the other options, this option specifies a \fBdirectory\fR,
|
||||
not a full path.
|
||||
|
||||
This option is primarily used by the SNAP packaging system, its semantics
|
||||
may change. It should not be neccessary in most other scenarios.
|
||||
|
||||
.SH MODULE LOADING
|
||||
@PACKAGE_NAME@ supports optional dynamically loadable modules, although
|
||||
these can only be loaded at startup. The set of available modules may vary
|
||||
across distributions and packages, and modules may be available for
|
||||
installation as separate packages.
|
||||
.TP
|
||||
\fB\-M\fR, \fB\-\-module\fR \fImodule\fR[\fB:\fIoptions\fR]
|
||||
Load a module named \fImodule\fR, optionally passing \fIoptions\fR to it.
|
||||
|
||||
If there is a \'/\' character in \fImodule\fR, the value is assumed to be
|
||||
a pathname to a module.
|
||||
|
||||
If there is no \'/\' character, the module directory (see next option)
|
||||
is searched first for a module named "\fI<daemon>\fB_\fI<module>\fB.so\fR",
|
||||
then for "\fI<module>\fB.so\fR".
|
||||
This allows for a module to exist in variations appropriate for particular
|
||||
daemons, e.g. \fIzebra_snmp\fR and \fIbgp_snmp\fR, with the correct one
|
||||
selected by \fI\-M snmp\fR.
|
||||
|
||||
The meaning of \fIoptions\fR is specific to the module being loaded. Most
|
||||
modules currently ignore it.
|
||||
|
||||
Modules are loaded in the order as listed on the command line. This is
|
||||
not generally relevant.
|
||||
.TP
|
||||
\fB\-\-moduledir\fR \fImodule-path\fR
|
||||
Look for modules in the \fImodule-path\fR directory instead of the default
|
||||
\fI@CFG_MODULE@\fR. (This path is \fBnot\fR affected by the \fB\-N\fR
|
||||
option.)
|
||||
.PP
|
||||
The list of loaded modules can be inspected at runtime with the
|
||||
\fBshow modules\fR VTY command.
|
||||
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR zebra (8),
|
||||
.BR vtysh (1),
|
||||
.BR ripd (8),
|
||||
.BR ripngd (8),
|
||||
.BR ospfd (8),
|
||||
.BR ospf6d (8),
|
||||
.BR bgpd (8),
|
||||
.BR isisd (8),
|
||||
.BR babeld (8),
|
||||
.BR nhrpd (8),
|
||||
.BR pimd (8),
|
||||
.BR ldpd (8),
|
||||
.BR eigrpd (8)
|
||||
|
||||
\fIhttps://frrouting.org/
|
@ -93,7 +93,7 @@ static int config_write_interfaces(struct vty *vty, struct eigrp *eigrp)
|
||||
struct listnode *node;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) {
|
||||
vty_out(vty, "interface %s\n", ei->ifp->name);
|
||||
vty_frame(vty, "interface %s\n", ei->ifp->name);
|
||||
|
||||
if ((IF_DEF_PARAMS(ei->ifp)->auth_type)
|
||||
== EIGRP_AUTH_TYPE_MD5) {
|
||||
@ -128,7 +128,7 @@ static int config_write_interfaces(struct vty *vty, struct eigrp *eigrp)
|
||||
}
|
||||
|
||||
/*Separate this EIGRP interface configuration from the others*/
|
||||
vty_out(vty, "!\n");
|
||||
vty_endframe(vty, "!\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -140,7 +140,7 @@ static int eigrp_write_interface(struct vty *vty)
|
||||
struct interface *ifp;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
|
||||
vty_out(vty, "interface %s\n", ifp->name);
|
||||
vty_frame(vty, "interface %s\n", ifp->name);
|
||||
|
||||
if (ifp->desc)
|
||||
vty_out(vty, " description %s\n", ifp->desc);
|
||||
@ -157,7 +157,7 @@ static int eigrp_write_interface(struct vty *vty)
|
||||
vty_out(vty, " ip hold-time eigrp %u\n",
|
||||
IF_DEF_PARAMS(ifp)->v_wait);
|
||||
|
||||
vty_out(vty, "!\n");
|
||||
vty_endframe(vty, "!\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -948,7 +948,7 @@ int isis_interface_config_write(struct vty *vty)
|
||||
continue;
|
||||
|
||||
/* IF name */
|
||||
vty_out(vty, "interface %s\n", ifp->name);
|
||||
vty_frame(vty, "interface %s\n", ifp->name);
|
||||
write++;
|
||||
/* IF desc */
|
||||
if (ifp->desc) {
|
||||
@ -1145,7 +1145,7 @@ int isis_interface_config_write(struct vty *vty)
|
||||
}
|
||||
write += circuit_write_mt_settings(circuit, vty);
|
||||
}
|
||||
vty_out(vty, "!\n");
|
||||
vty_endframe(vty, "!\n");
|
||||
}
|
||||
|
||||
return write;
|
||||
|
50
lib/libfrr.c
50
lib/libfrr.c
@ -101,13 +101,15 @@ static const struct optspec os_always = {
|
||||
static const struct option lo_cfg_pid_dry[] = {
|
||||
{"pid_file", required_argument, NULL, 'i'},
|
||||
{"config_file", required_argument, NULL, 'f'},
|
||||
{"pathspace", required_argument, NULL, 'N'},
|
||||
{"dryrun", no_argument, NULL, 'C'},
|
||||
{"terminal", no_argument, NULL, 't'},
|
||||
{NULL}};
|
||||
static const struct optspec os_cfg_pid_dry = {
|
||||
"f:i:Ct",
|
||||
"f:i:CtN:",
|
||||
" -f, --config_file Set configuration file name\n"
|
||||
" -i, --pid_file Set process identifier file name\n"
|
||||
" -N, --pathspace Insert prefix into config & socket paths\n"
|
||||
" -C, --dryrun Check configuration for validity and exit\n"
|
||||
" -t, --terminal Open terminal session on stdio\n"
|
||||
" -d -t Daemonize after terminal session ends\n",
|
||||
@ -351,6 +353,23 @@ static int frr_opt(int opt)
|
||||
return 1;
|
||||
di->config_file = optarg;
|
||||
break;
|
||||
case 'N':
|
||||
if (di->flags & FRR_NO_CFG_PID_DRY)
|
||||
return 1;
|
||||
if (di->pathspace) {
|
||||
fprintf(stderr,
|
||||
"-N/--pathspace option specified more than once!\n");
|
||||
errors++;
|
||||
break;
|
||||
}
|
||||
if (strchr(optarg, '/') || strchr(optarg, '.')) {
|
||||
fprintf(stderr,
|
||||
"slashes or dots are not permitted in the --pathspace option.\n");
|
||||
errors++;
|
||||
break;
|
||||
}
|
||||
di->pathspace = optarg;
|
||||
break;
|
||||
case 'C':
|
||||
if (di->flags & FRR_NO_CFG_PID_DRY)
|
||||
return 1;
|
||||
@ -500,14 +519,25 @@ struct thread_master *frr_init(void)
|
||||
struct option_chain *oc;
|
||||
struct frrmod_runtime *module;
|
||||
char moderr[256];
|
||||
char p_instance[16] = "", p_pathspace[256] = "";
|
||||
const char *dir;
|
||||
dir = di->module_path ? di->module_path : frr_moduledir;
|
||||
|
||||
srandom(time(NULL));
|
||||
|
||||
if (di->instance)
|
||||
if (di->instance) {
|
||||
snprintf(frr_protonameinst, sizeof(frr_protonameinst), "%s[%u]",
|
||||
di->logname, di->instance);
|
||||
snprintf(p_instance, sizeof(p_instance), "-%d", di->instance);
|
||||
}
|
||||
if (di->pathspace)
|
||||
snprintf(p_pathspace, sizeof(p_pathspace), "/%s",
|
||||
di->pathspace);
|
||||
|
||||
snprintf(config_default, sizeof(config_default), "%s%s/%s%s.conf",
|
||||
frr_sysconfdir, p_pathspace, di->name, p_instance);
|
||||
snprintf(pidfile_default, sizeof(pidfile_default), "%s%s/%s%s.pid",
|
||||
frr_vtydir, p_pathspace, di->name, p_instance);
|
||||
|
||||
zprivs_preinit(di->privs);
|
||||
|
||||
@ -695,14 +725,6 @@ void frr_config_fork(void)
|
||||
{
|
||||
hook_call(frr_late_init, master);
|
||||
|
||||
if (di->instance) {
|
||||
snprintf(config_default, sizeof(config_default),
|
||||
"%s/%s-%d.conf", frr_sysconfdir, di->name,
|
||||
di->instance);
|
||||
snprintf(pidfile_default, sizeof(pidfile_default),
|
||||
"%s/%s-%d.pid", frr_vtydir, di->name, di->instance);
|
||||
}
|
||||
|
||||
vty_read_config(di->config_file, config_default);
|
||||
|
||||
/* Don't start execution if we are in dry-run mode */
|
||||
@ -723,7 +745,13 @@ void frr_vty_serv(void)
|
||||
* (not currently set anywhere) */
|
||||
if (!di->vty_path) {
|
||||
const char *dir;
|
||||
dir = di->vty_sock_path ? di->vty_sock_path : frr_vtydir;
|
||||
char defvtydir[256];
|
||||
|
||||
snprintf(defvtydir, sizeof(defvtydir), "%s%s%s", frr_vtydir,
|
||||
di->pathspace ? "/" : "",
|
||||
di->pathspace ? di->pathspace : "");
|
||||
|
||||
dir = di->vty_sock_path ? di->vty_sock_path : defvtydir;
|
||||
|
||||
if (di->instance)
|
||||
snprintf(vtypath_default, sizeof(vtypath_default),
|
||||
|
@ -54,6 +54,7 @@ struct frr_daemon_info {
|
||||
const char *pid_file;
|
||||
const char *vty_path;
|
||||
const char *module_path;
|
||||
const char *pathspace;
|
||||
|
||||
const char *proghelp;
|
||||
void (*printhelp)(FILE *target);
|
||||
|
24
lib/vty.c
24
lib/vty.c
@ -91,6 +91,25 @@ char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG;
|
||||
|
||||
static int do_log_commands = 0;
|
||||
|
||||
void vty_frame(struct vty *vty, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
vsnprintf(vty->frame + vty->frame_pos,
|
||||
sizeof(vty->frame) - vty->frame_pos,
|
||||
format, args);
|
||||
vty->frame_pos = strlen(vty->frame);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void vty_endframe(struct vty *vty, const char *endtext)
|
||||
{
|
||||
if (vty->frame_pos == 0 && endtext)
|
||||
vty_out(vty, "%s", endtext);
|
||||
vty->frame_pos = 0;
|
||||
}
|
||||
|
||||
/* VTY standard output function. */
|
||||
int vty_out(struct vty *vty, const char *format, ...)
|
||||
{
|
||||
@ -100,6 +119,11 @@ int vty_out(struct vty *vty, const char *format, ...)
|
||||
char buf[1024];
|
||||
char *p = NULL;
|
||||
|
||||
if (vty->frame_pos) {
|
||||
vty->frame_pos = 0;
|
||||
vty_out(vty, "%s", vty->frame);
|
||||
}
|
||||
|
||||
if (vty_shell(vty)) {
|
||||
va_start(args, format);
|
||||
vprintf(format, args);
|
||||
|
15
lib/vty.h
15
lib/vty.h
@ -125,6 +125,12 @@ struct vty {
|
||||
|
||||
/* What address is this vty comming from. */
|
||||
char address[SU_ADDRSTRLEN];
|
||||
|
||||
/* "frame" output. This is buffered and will be printed if some
|
||||
* actual output follows, or will be discarded if the frame ends
|
||||
* without any output. */
|
||||
size_t frame_pos;
|
||||
char frame[1024];
|
||||
};
|
||||
|
||||
static inline void vty_push_context(struct vty *vty, int node, uint64_t id)
|
||||
@ -247,7 +253,16 @@ extern void vty_terminate(void);
|
||||
extern void vty_reset(void);
|
||||
extern struct vty *vty_new(void);
|
||||
extern struct vty *vty_stdio(void (*atclose)(int isexit));
|
||||
|
||||
/* - vty_frame() output goes to a buffer (for context-begin markers)
|
||||
* - vty_out() will first print this buffer, and clear it
|
||||
* - vty_endframe() clears the buffer without printing it, and prints an
|
||||
* extra string if the buffer was empty before (for context-end markers)
|
||||
*/
|
||||
extern int vty_out(struct vty *, const char *, ...) PRINTF_ATTRIBUTE(2, 3);
|
||||
extern void vty_frame(struct vty *, const char *, ...) PRINTF_ATTRIBUTE(2, 3);
|
||||
extern void vty_endframe(struct vty *, const char *);
|
||||
|
||||
extern void vty_read_config(const char *, char *);
|
||||
extern void vty_time_print(struct vty *, int);
|
||||
extern void vty_serv_sock(const char *, unsigned short, const char *);
|
||||
|
@ -854,7 +854,7 @@ static int interface_config_write(struct vty *vty)
|
||||
int i;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
|
||||
vty_out (vty, "interface %s\n", ifp->name);
|
||||
vty_frame(vty, "interface %s\n", ifp->name);
|
||||
if (ifp->desc)
|
||||
vty_out (vty, " description %s\n", ifp->desc);
|
||||
|
||||
@ -913,7 +913,7 @@ static int interface_config_write(struct vty *vty)
|
||||
}
|
||||
}
|
||||
|
||||
vty_out (vty, "!\n");
|
||||
vty_endframe(vty, "!\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1755,7 +1755,7 @@ static int config_write_ospf6_interface(struct vty *vty)
|
||||
if (oi == NULL)
|
||||
continue;
|
||||
|
||||
vty_out(vty, "interface %s\n", oi->interface->name);
|
||||
vty_frame(vty, "interface %s\n", oi->interface->name);
|
||||
|
||||
if (ifp->desc)
|
||||
vty_out(vty, " description %s\n", ifp->desc);
|
||||
@ -1808,7 +1808,7 @@ static int config_write_ospf6_interface(struct vty *vty)
|
||||
|
||||
ospf6_bfd_write_config(vty, oi);
|
||||
|
||||
vty_out(vty, "!\n");
|
||||
vty_endframe(vty, "!\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -8156,8 +8156,8 @@ static int config_write_interface(struct vty *vty)
|
||||
if (ifp->ifindex == IFINDEX_DELETED)
|
||||
continue;
|
||||
|
||||
vty_out(vty, "!\n");
|
||||
vty_out(vty, "interface %s\n", ifp->name);
|
||||
vty_frame(vty, "!\n");
|
||||
vty_frame(vty, "interface %s\n", ifp->name);
|
||||
if (ifp->desc)
|
||||
vty_out(vty, " description %s\n", ifp->desc);
|
||||
|
||||
@ -8371,6 +8371,8 @@ static int config_write_interface(struct vty *vty)
|
||||
} while (rn);
|
||||
|
||||
ospf_opaque_config_write_if(vty, ifp);
|
||||
|
||||
vty_endframe(vty, NULL);
|
||||
}
|
||||
|
||||
return write;
|
||||
|
@ -255,7 +255,7 @@ int pim_interface_config_write(struct vty *vty)
|
||||
|
||||
/* IF name */
|
||||
if (vrf->vrf_id == VRF_DEFAULT)
|
||||
vty_out(vty, "interface %s\n", ifp->name);
|
||||
vty_frame(vty, "interface %s\n", ifp->name);
|
||||
else
|
||||
vty_out(vty, "interface %s vrf %s\n", ifp->name,
|
||||
vrf->name);
|
||||
@ -363,7 +363,7 @@ int pim_interface_config_write(struct vty *vty)
|
||||
pim_static_write_mroute(pim, vty, ifp);
|
||||
pim_bfd_write_config(vty, ifp);
|
||||
}
|
||||
vty_out(vty, "!\n");
|
||||
vty_endframe(vty, "!\n");
|
||||
++writes;
|
||||
}
|
||||
}
|
||||
|
@ -1751,7 +1751,7 @@ static int rip_interface_config_write(struct vty *vty)
|
||||
&& (!ri->auth_str) && (!ri->key_chain))
|
||||
continue;
|
||||
|
||||
vty_out(vty, "interface %s\n", ifp->name);
|
||||
vty_frame(vty, "interface %s\n", ifp->name);
|
||||
|
||||
if (ifp->desc)
|
||||
vty_out(vty, " description %s\n", ifp->desc);
|
||||
@ -1807,7 +1807,7 @@ static int rip_interface_config_write(struct vty *vty)
|
||||
vty_out(vty, " ip rip authentication key-chain %s\n",
|
||||
ri->key_chain);
|
||||
|
||||
vty_out(vty, "!\n");
|
||||
vty_endframe(vty, "!\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1084,7 +1084,7 @@ static int interface_config_write(struct vty *vty)
|
||||
&& (ri->split_horizon == ri->split_horizon_default))
|
||||
continue;
|
||||
|
||||
vty_out(vty, "interface %s\n", ifp->name);
|
||||
vty_frame(vty, "interface %s\n", ifp->name);
|
||||
if (ifp->desc)
|
||||
vty_out(vty, " description %s\n", ifp->desc);
|
||||
|
||||
@ -1105,7 +1105,7 @@ static int interface_config_write(struct vty *vty)
|
||||
}
|
||||
}
|
||||
|
||||
vty_out(vty, "!\n");
|
||||
vty_endframe(vty, "!\n");
|
||||
|
||||
write++;
|
||||
}
|
||||
|
@ -2295,12 +2295,12 @@ int vtysh_write_config_integrated(void)
|
||||
|
||||
fprintf(stdout, "Building Configuration...\n");
|
||||
|
||||
backup_config_file(quagga_config);
|
||||
fp = fopen(quagga_config, "w");
|
||||
backup_config_file(frr_config);
|
||||
fp = fopen(frr_config, "w");
|
||||
if (fp == NULL) {
|
||||
fprintf(stdout,
|
||||
"%% Error: failed to open configuration file %s: %s\n",
|
||||
quagga_config, safe_strerror(errno));
|
||||
frr_config, safe_strerror(errno));
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
fd = fileno(fp);
|
||||
@ -2313,7 +2313,7 @@ int vtysh_write_config_integrated(void)
|
||||
|
||||
if (fchmod(fd, CONFIGFILE_MASK) != 0) {
|
||||
printf("%% Warning: can't chmod configuration file %s: %s\n",
|
||||
quagga_config, safe_strerror(errno));
|
||||
frr_config, safe_strerror(errno));
|
||||
err++;
|
||||
}
|
||||
|
||||
@ -2345,18 +2345,18 @@ int vtysh_write_config_integrated(void)
|
||||
if ((uid != (uid_t)-1 || gid != (gid_t)-1)
|
||||
&& fchown(fd, uid, gid)) {
|
||||
printf("%% Warning: can't chown configuration file %s: %s\n",
|
||||
quagga_config, safe_strerror(errno));
|
||||
frr_config, safe_strerror(errno));
|
||||
err++;
|
||||
}
|
||||
} else {
|
||||
printf("%% Warning: stat() failed on %s: %s\n", quagga_config,
|
||||
printf("%% Warning: stat() failed on %s: %s\n", frr_config,
|
||||
safe_strerror(errno));
|
||||
err++;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
printf("Integrated configuration saved to %s\n", quagga_config);
|
||||
printf("Integrated configuration saved to %s\n", frr_config);
|
||||
if (err)
|
||||
return CMD_WARNING;
|
||||
|
||||
@ -2370,7 +2370,7 @@ static bool want_config_integrated(void)
|
||||
|
||||
switch (vtysh_write_integrated) {
|
||||
case WRITE_INTEGRATED_UNSPECIFIED:
|
||||
if (stat(quagga_config, &s) && errno == ENOENT)
|
||||
if (stat(frr_config, &s) && errno == ENOENT)
|
||||
return false;
|
||||
return true;
|
||||
case WRITE_INTEGRATED_NO:
|
||||
@ -2712,7 +2712,7 @@ static int vtysh_connect(struct vtysh_client *vclient)
|
||||
|
||||
if (!vclient->path[0])
|
||||
snprintf(vclient->path, sizeof(vclient->path), "%s/%s.vty",
|
||||
vty_sock_path, vclient->name);
|
||||
vtydir, vclient->name);
|
||||
path = vclient->path;
|
||||
|
||||
/* Stat socket to see if we have permission to access it. */
|
||||
@ -2806,7 +2806,7 @@ static void vtysh_update_all_insances(struct vtysh_client *head_client)
|
||||
return;
|
||||
|
||||
/* ls vty_sock_dir and look for all files ending in .vty */
|
||||
dir = opendir(vty_sock_path);
|
||||
dir = opendir(vtydir);
|
||||
if (dir) {
|
||||
while ((file = readdir(dir)) != NULL) {
|
||||
if (begins_with(file->d_name, "ospfd-")
|
||||
@ -2814,7 +2814,7 @@ static void vtysh_update_all_insances(struct vtysh_client *head_client)
|
||||
if (n == MAXIMUM_INSTANCES) {
|
||||
fprintf(stderr,
|
||||
"Parsing %s, client limit(%d) reached!\n",
|
||||
vty_sock_path, n);
|
||||
vtydir, n);
|
||||
break;
|
||||
}
|
||||
client = (struct vtysh_client *)malloc(
|
||||
@ -2823,7 +2823,7 @@ static void vtysh_update_all_insances(struct vtysh_client *head_client)
|
||||
client->name = "ospfd";
|
||||
client->flag = VTYSH_OSPFD;
|
||||
snprintf(client->path, sizeof(client->path),
|
||||
"%s/%s", vty_sock_path, file->d_name);
|
||||
"%s/%s", vtydir, file->d_name);
|
||||
client->next = NULL;
|
||||
vtysh_client_sorted_insert(head_client, client);
|
||||
n++;
|
||||
|
@ -49,10 +49,6 @@ DECLARE_MGROUP(MVTYSH)
|
||||
#define VTYSH_NS VTYSH_ZEBRA
|
||||
#define VTYSH_VRF VTYSH_ZEBRA|VTYSH_PIMD
|
||||
|
||||
/* vtysh local configuration file. */
|
||||
#define VTYSH_DEFAULT_CONFIG "vtysh.conf"
|
||||
#define FRR_DEFAULT_CONFIG "frr.conf"
|
||||
|
||||
enum vtysh_write_integrated {
|
||||
WRITE_INTEGRATED_UNSPECIFIED,
|
||||
WRITE_INTEGRATED_NO,
|
||||
@ -61,7 +57,8 @@ enum vtysh_write_integrated {
|
||||
|
||||
extern enum vtysh_write_integrated vtysh_write_integrated;
|
||||
|
||||
extern char *quagga_config;
|
||||
extern char frr_config[];
|
||||
extern char vtydir[];
|
||||
|
||||
void vtysh_init_vty(void);
|
||||
void vtysh_init_cmd(void);
|
||||
@ -93,11 +90,12 @@ void vtysh_config_init(void);
|
||||
|
||||
void vtysh_pager_init(void);
|
||||
|
||||
void suid_on(void);
|
||||
void suid_off(void);
|
||||
|
||||
/* Child process execution flag. */
|
||||
extern int execute_flag;
|
||||
|
||||
extern struct vty *vty;
|
||||
|
||||
extern const char *vty_sock_path;
|
||||
|
||||
#endif /* VTYSH_H */
|
||||
|
@ -44,18 +44,22 @@
|
||||
/* VTY shell program name. */
|
||||
char *progname;
|
||||
|
||||
/* SUID mode */
|
||||
static uid_t elevuid, realuid;
|
||||
static gid_t elevgid, realgid;
|
||||
|
||||
#define VTYSH_CONFIG_NAME "vtysh.conf"
|
||||
#define FRR_CONFIG_NAME "frr.conf"
|
||||
|
||||
/* Configuration file name and directory. */
|
||||
static char vtysh_config_always[MAXPATHLEN] = SYSCONFDIR VTYSH_DEFAULT_CONFIG;
|
||||
static char quagga_config_default[MAXPATHLEN] = SYSCONFDIR FRR_DEFAULT_CONFIG;
|
||||
char *quagga_config = quagga_config_default;
|
||||
char history_file[MAXPATHLEN];
|
||||
static char vtysh_config[MAXPATHLEN];
|
||||
char frr_config[MAXPATHLEN];
|
||||
char vtydir[MAXPATHLEN];
|
||||
static char history_file[MAXPATHLEN];
|
||||
|
||||
/* Flag for indicate executing child command. */
|
||||
int execute_flag = 0;
|
||||
|
||||
/* VTY Socket prefix */
|
||||
const char *vty_sock_path = NULL;
|
||||
|
||||
/* For sigsetjmp() & siglongjmp(). */
|
||||
static sigjmp_buf jmpbuf;
|
||||
|
||||
@ -145,6 +149,7 @@ static void usage(int status)
|
||||
"-m, --markfile Mark input file with context end\n"
|
||||
" --vty_socket Override vty socket path\n"
|
||||
" --config_dir Override config directory path\n"
|
||||
"-N --pathspace Insert prefix into config & socket paths\n"
|
||||
"-w, --writeconfig Write integrated config (frr.conf) and exit\n"
|
||||
"-h, --help Display this help and exit\n\n"
|
||||
"Note that multiple commands may be executed from the command\n"
|
||||
@ -174,6 +179,7 @@ struct option longopts[] = {
|
||||
{"noerror", no_argument, NULL, 'n'},
|
||||
{"mark", no_argument, NULL, 'm'},
|
||||
{"writeconfig", no_argument, NULL, 'w'},
|
||||
{"pathspace", no_argument, NULL, 'N'},
|
||||
{0}};
|
||||
|
||||
/* Read a string, and return a pointer to it. Returns NULL on EOF. */
|
||||
@ -249,6 +255,30 @@ static void vtysh_unflock_config(void)
|
||||
close(flock_fd);
|
||||
}
|
||||
|
||||
void suid_on(void)
|
||||
{
|
||||
if (elevuid != realuid && seteuid(elevuid)) {
|
||||
perror("seteuid(on)");
|
||||
exit(1);
|
||||
}
|
||||
if (elevgid != realgid && setegid(elevgid)) {
|
||||
perror("setegid(on)");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void suid_off(void)
|
||||
{
|
||||
if (elevuid != realuid && seteuid(realuid)) {
|
||||
perror("seteuid(off)");
|
||||
exit(1);
|
||||
}
|
||||
if (elevgid != realgid && setegid(realgid)) {
|
||||
perror("setegid(off)");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* VTY shell main routine. */
|
||||
int main(int argc, char **argv, char **env)
|
||||
{
|
||||
@ -258,7 +288,6 @@ int main(int argc, char **argv, char **env)
|
||||
int boot_flag = 0;
|
||||
const char *daemon_name = NULL;
|
||||
const char *inputfile = NULL;
|
||||
const char *vtysh_configfile_name;
|
||||
struct cmd_rec {
|
||||
char *line;
|
||||
struct cmd_rec *next;
|
||||
@ -270,16 +299,22 @@ int main(int argc, char **argv, char **env)
|
||||
int writeconfig = 0;
|
||||
int ret = 0;
|
||||
char *homedir = NULL;
|
||||
int ditch_suid = 0;
|
||||
char sysconfdir[MAXPATHLEN];
|
||||
char pathspace[MAXPATHLEN] = "";
|
||||
|
||||
/* check for restricted functionality if vtysh is run setuid */
|
||||
int restricted = (getuid() != geteuid()) || (getgid() != getegid());
|
||||
/* SUID: drop down to calling user & go back up when needed */
|
||||
elevuid = geteuid();
|
||||
elevgid = getegid();
|
||||
realuid = getuid();
|
||||
realgid = getgid();
|
||||
suid_off();
|
||||
|
||||
/* Preserve name of myself. */
|
||||
progname = ((p = strrchr(argv[0], '/')) ? ++p : argv[0]);
|
||||
|
||||
/* if logging open now */
|
||||
if ((p = getenv("VTYSH_LOG")) != NULL)
|
||||
logfile = fopen(p, "a");
|
||||
strlcpy(sysconfdir, frr_sysconfdir, sizeof(sysconfdir));
|
||||
strlcpy(vtydir, frr_vtydir, sizeof(vtydir));
|
||||
|
||||
/* Option handling. */
|
||||
while (1) {
|
||||
@ -307,63 +342,20 @@ int main(int argc, char **argv, char **env)
|
||||
tail = cr;
|
||||
} break;
|
||||
case OPTION_VTYSOCK:
|
||||
vty_sock_path = optarg;
|
||||
ditch_suid = 1; /* option disables SUID */
|
||||
strlcpy(vtydir, optarg, sizeof(vtydir));
|
||||
break;
|
||||
case OPTION_CONFDIR:
|
||||
/*
|
||||
* Skip option for Config Directory if setuid
|
||||
*/
|
||||
if (restricted) {
|
||||
ditch_suid = 1; /* option disables SUID */
|
||||
strlcpy(sysconfdir, optarg, sizeof(sysconfdir));
|
||||
break;
|
||||
case 'N':
|
||||
if (strchr(optarg, '/') || strchr(optarg, '.')) {
|
||||
fprintf(stderr,
|
||||
"Overriding of Config Directory blocked for vtysh with setuid");
|
||||
return 1;
|
||||
"slashes or dots are not permitted in the --pathspace option.\n");
|
||||
exit(1);
|
||||
}
|
||||
/*
|
||||
* Overwrite location for vtysh.conf
|
||||
*/
|
||||
vtysh_configfile_name =
|
||||
strrchr(VTYSH_DEFAULT_CONFIG, '/');
|
||||
if (vtysh_configfile_name)
|
||||
/* skip '/' */
|
||||
vtysh_configfile_name++;
|
||||
else
|
||||
/*
|
||||
* VTYSH_DEFAULT_CONFIG configured with relative
|
||||
* path
|
||||
* during config? Should really never happen for
|
||||
* sensible config
|
||||
*/
|
||||
vtysh_configfile_name =
|
||||
(char *)VTYSH_DEFAULT_CONFIG;
|
||||
strlcpy(vtysh_config_always, optarg,
|
||||
sizeof(vtysh_config_always));
|
||||
strlcat(vtysh_config_always, "/",
|
||||
sizeof(vtysh_config_always));
|
||||
strlcat(vtysh_config_always, vtysh_configfile_name,
|
||||
sizeof(vtysh_config_always));
|
||||
/*
|
||||
* Overwrite location for frr.conf
|
||||
*/
|
||||
vtysh_configfile_name =
|
||||
strrchr(FRR_DEFAULT_CONFIG, '/');
|
||||
if (vtysh_configfile_name)
|
||||
/* skip '/' */
|
||||
vtysh_configfile_name++;
|
||||
else
|
||||
/*
|
||||
* FRR_DEFAULT_CONFIG configured with relative
|
||||
* path
|
||||
* during config? Should really never happen for
|
||||
* sensible config
|
||||
*/
|
||||
vtysh_configfile_name =
|
||||
(char *)FRR_DEFAULT_CONFIG;
|
||||
strlcpy(quagga_config_default, optarg,
|
||||
sizeof(vtysh_config_always));
|
||||
strlcat(quagga_config_default, "/",
|
||||
sizeof(vtysh_config_always));
|
||||
strlcat(quagga_config_default, vtysh_configfile_name,
|
||||
sizeof(quagga_config_default));
|
||||
snprintf(pathspace, sizeof(pathspace), "/%s", optarg);
|
||||
break;
|
||||
case 'd':
|
||||
daemon_name = optarg;
|
||||
@ -395,8 +387,10 @@ int main(int argc, char **argv, char **env)
|
||||
}
|
||||
}
|
||||
|
||||
if (!vty_sock_path)
|
||||
vty_sock_path = frr_vtydir;
|
||||
if (ditch_suid) {
|
||||
elevuid = realuid;
|
||||
elevgid = realgid;
|
||||
}
|
||||
|
||||
if (markfile + writeconfig + dryrun + boot_flag > 1) {
|
||||
fprintf(stderr,
|
||||
@ -410,6 +404,12 @@ int main(int argc, char **argv, char **env)
|
||||
"NOT SUPPORTED since its\nresults are inconsistent!\n");
|
||||
}
|
||||
|
||||
snprintf(vtysh_config, sizeof(vtysh_config), "%s%s/%s",
|
||||
sysconfdir, pathspace, VTYSH_CONFIG_NAME);
|
||||
snprintf(frr_config, sizeof(frr_config), "%s%s/%s",
|
||||
sysconfdir, pathspace, FRR_CONFIG_NAME);
|
||||
strlcat(vtydir, pathspace, sizeof(vtydir));
|
||||
|
||||
/* Initialize user input buffer. */
|
||||
line_read = NULL;
|
||||
setlinebuf(stdout);
|
||||
@ -425,8 +425,11 @@ int main(int argc, char **argv, char **env)
|
||||
|
||||
vty_init_vtysh();
|
||||
|
||||
/* Read vtysh configuration file before connecting to daemons. */
|
||||
vtysh_read_config(vtysh_config_always);
|
||||
/* Read vtysh configuration file before connecting to daemons.
|
||||
* (file may not be readable to calling user in SUID mode) */
|
||||
suid_on();
|
||||
vtysh_read_config(vtysh_config);
|
||||
suid_off();
|
||||
|
||||
if (markfile) {
|
||||
if (!inputfile) {
|
||||
@ -442,7 +445,7 @@ int main(int argc, char **argv, char **env)
|
||||
if (inputfile) {
|
||||
ret = vtysh_read_config(inputfile);
|
||||
} else {
|
||||
ret = vtysh_read_config(quagga_config_default);
|
||||
ret = vtysh_read_config(frr_config);
|
||||
}
|
||||
|
||||
exit(ret);
|
||||
@ -486,6 +489,9 @@ int main(int argc, char **argv, char **env)
|
||||
}
|
||||
}
|
||||
|
||||
/* SUID: go back up elevated privs */
|
||||
suid_on();
|
||||
|
||||
/* Make sure we pass authentication before proceeding. */
|
||||
vtysh_auth();
|
||||
|
||||
@ -498,6 +504,9 @@ int main(int argc, char **argv, char **env)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* SUID: back down, don't need privs further on */
|
||||
suid_off();
|
||||
|
||||
if (writeconfig) {
|
||||
vtysh_execute("enable");
|
||||
return vtysh_write_config_integrated();
|
||||
@ -531,6 +540,17 @@ int main(int argc, char **argv, char **env)
|
||||
}
|
||||
}
|
||||
|
||||
if (getenv("VTYSH_LOG")) {
|
||||
const char *logpath = getenv("VTYSH_LOG");
|
||||
|
||||
logfile = fopen(logpath, "a");
|
||||
if (!logfile) {
|
||||
fprintf(stderr, "Failed to open logfile (%s): %s\n",
|
||||
logpath, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* If eval mode. */
|
||||
if (cmd) {
|
||||
/* Enter into enable node. */
|
||||
@ -592,13 +612,13 @@ int main(int argc, char **argv, char **env)
|
||||
|
||||
/* Boot startup configuration file. */
|
||||
if (boot_flag) {
|
||||
vtysh_flock_config(quagga_config);
|
||||
int ret = vtysh_read_config(quagga_config);
|
||||
vtysh_flock_config(frr_config);
|
||||
int ret = vtysh_read_config(frr_config);
|
||||
vtysh_unflock_config();
|
||||
if (ret) {
|
||||
fprintf(stderr,
|
||||
"Configuration file[%s] processing failure: %d\n",
|
||||
quagga_config, ret);
|
||||
frr_config, ret);
|
||||
if (no_error)
|
||||
exit(0);
|
||||
else
|
||||
|
@ -2793,7 +2793,7 @@ static int if_config_write(struct vty *vty)
|
||||
vrf = vrf_lookup_by_id(ifp->vrf_id);
|
||||
|
||||
if (ifp->vrf_id == VRF_DEFAULT)
|
||||
vty_out(vty, "interface %s\n", ifp->name);
|
||||
vty_frame(vty, "interface %s\n", ifp->name);
|
||||
else
|
||||
vty_out(vty, "interface %s vrf %s\n", ifp->name,
|
||||
vrf->name);
|
||||
@ -2844,7 +2844,7 @@ static int if_config_write(struct vty *vty)
|
||||
|
||||
link_params_config_write(vty, ifp);
|
||||
|
||||
vty_out(vty, "!\n");
|
||||
vty_endframe(vty, "!\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user