mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-08 05:00:23 +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;
|
int write = 0;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO (vrf_iflist(VRF_DEFAULT), node, 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)
|
if (ifp->desc)
|
||||||
vty_out (vty, " description %s\n",ifp->desc);
|
vty_out (vty, " description %s\n",ifp->desc);
|
||||||
babel_interface_nfo *babel_ifp = babel_get_if_nfo (ifp);
|
babel_interface_nfo *babel_ifp = babel_get_if_nfo (ifp);
|
||||||
@ -1377,7 +1377,7 @@ interface_config_write (struct vty *vty)
|
|||||||
write++;
|
write++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vty_out (vty, "!\n");
|
vty_endframe (vty, "!\n");
|
||||||
write++;
|
write++;
|
||||||
}
|
}
|
||||||
return write;
|
return write;
|
||||||
|
@ -50,11 +50,6 @@ struct vni_walk_ctx {
|
|||||||
json_object *json;
|
json_object *json;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct evpn_config_write {
|
|
||||||
int write;
|
|
||||||
struct vty *vty;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined(HAVE_CUMULUS)
|
#if defined(HAVE_CUMULUS)
|
||||||
static void display_import_rt(struct vty *vty, struct irt_node *irt,
|
static void display_import_rt(struct vty *vty, struct irt_node *irt,
|
||||||
json_object *json)
|
json_object *json)
|
||||||
@ -587,7 +582,9 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
|
|||||||
if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
|
if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((table = rn->info) != NULL) {
|
if ((table = rn->info) == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
rd_header = 1;
|
rd_header = 1;
|
||||||
|
|
||||||
for (rm = bgp_table_top(table); rm;
|
for (rm = bgp_table_top(table); rm;
|
||||||
@ -663,14 +660,11 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
|
|||||||
type = decode_rd_type(pnt);
|
type = decode_rd_type(pnt);
|
||||||
/* Decode RD value. */
|
/* Decode RD value. */
|
||||||
if (type == RD_TYPE_AS)
|
if (type == RD_TYPE_AS)
|
||||||
decode_rd_as(pnt + 2,
|
decode_rd_as(pnt + 2, &rd_as);
|
||||||
&rd_as);
|
|
||||||
else if (type == RD_TYPE_AS4)
|
else if (type == RD_TYPE_AS4)
|
||||||
decode_rd_as4(pnt + 2,
|
decode_rd_as4(pnt + 2, &rd_as);
|
||||||
&rd_as);
|
|
||||||
else if (type == RD_TYPE_IP)
|
else if (type == RD_TYPE_IP)
|
||||||
decode_rd_ip(pnt + 2,
|
decode_rd_ip(pnt + 2, &rd_ip);
|
||||||
&rd_ip);
|
|
||||||
if (use_json) {
|
if (use_json) {
|
||||||
char buffer[BUFSIZ];
|
char buffer[BUFSIZ];
|
||||||
if (type == RD_TYPE_AS
|
if (type == RD_TYPE_AS
|
||||||
@ -716,27 +710,23 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
|
|||||||
rd_header = 0;
|
rd_header = 0;
|
||||||
}
|
}
|
||||||
if (use_json)
|
if (use_json)
|
||||||
json_array =
|
json_array = json_object_new_array();
|
||||||
json_object_new_array();
|
|
||||||
else
|
else
|
||||||
json_array = NULL;
|
json_array = NULL;
|
||||||
if (option == SHOW_DISPLAY_TAGS)
|
if (option == SHOW_DISPLAY_TAGS)
|
||||||
route_vty_out_tag(
|
route_vty_out_tag(vty, &rm->p, ri, 0,
|
||||||
vty, &rm->p, ri, 0,
|
SAFI_EVPN,
|
||||||
SAFI_EVPN, json_array);
|
json_array);
|
||||||
else if (option == SHOW_DISPLAY_OVERLAY)
|
else if (option == SHOW_DISPLAY_OVERLAY)
|
||||||
route_vty_out_overlay(
|
route_vty_out_overlay(vty, &rm->p, ri,
|
||||||
vty, &rm->p, ri, 0,
|
0, json_array);
|
||||||
json_array);
|
|
||||||
else
|
else
|
||||||
route_vty_out(vty, &rm->p, ri,
|
route_vty_out(vty, &rm->p, ri, 0,
|
||||||
0, SAFI_EVPN,
|
SAFI_EVPN, json_array);
|
||||||
json_array);
|
|
||||||
output_count++;
|
output_count++;
|
||||||
}
|
}
|
||||||
/* XXX json */
|
/* XXX json */
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (output_count == 0)
|
if (output_count == 0)
|
||||||
vty_out(vty, "No prefixes displayed, %ld exist\n", total_count);
|
vty_out(vty, "No prefixes displayed, %ld exist\n", total_count);
|
||||||
else
|
else
|
||||||
@ -2125,17 +2115,14 @@ static void evpn_unset_advertise_all_vni(struct bgp *bgp)
|
|||||||
}
|
}
|
||||||
#endif /* HAVE_CUMULUS */
|
#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];
|
char buf1[INET6_ADDRSTRLEN];
|
||||||
afi_t afi = AFI_L2VPN;
|
|
||||||
safi_t safi = SAFI_EVPN;
|
|
||||||
char *ecom_str;
|
char *ecom_str;
|
||||||
struct listnode *node, *nnode;
|
struct listnode *node, *nnode;
|
||||||
struct ecommunity *ecom;
|
struct ecommunity *ecom;
|
||||||
|
|
||||||
if (is_vni_configured(vpn)) {
|
if (is_vni_configured(vpn)) {
|
||||||
bgp_config_write_family_header(vty, afi, safi, write);
|
|
||||||
vty_out(vty, " vni %d\n", vpn->vni);
|
vty_out(vty, " vni %d\n", vpn->vni);
|
||||||
if (is_rd_configured(vpn))
|
if (is_rd_configured(vpn))
|
||||||
vty_out(vty, " rd %s\n",
|
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,
|
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;
|
struct bgpevpn *vpn = (struct bgpevpn *)backet->data;
|
||||||
write_vni_config(cfg->vty, vpn, &cfg->write);
|
write_vni_config(vty, vpn);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_CUMULUS)
|
#if defined(HAVE_CUMULUS)
|
||||||
@ -3326,30 +3313,20 @@ DEFUN (no_bgp_evpn_vni_rt_without_val,
|
|||||||
* Output EVPN configuration information.
|
* Output EVPN configuration information.
|
||||||
*/
|
*/
|
||||||
void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
|
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)
|
||||||
|
|
||||||
if (bgp->vnihash) {
|
|
||||||
cfg.write = *write;
|
|
||||||
cfg.vty = vty;
|
|
||||||
hash_iterate(bgp->vnihash,
|
hash_iterate(bgp->vnihash,
|
||||||
(void (*)(struct hash_backet *,
|
(void (*)(struct hash_backet *,
|
||||||
void *))write_vni_config_for_entry,
|
void *))write_vni_config_for_entry,
|
||||||
&cfg);
|
vty);
|
||||||
*write = cfg.write;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bgp->advertise_all_vni) {
|
if (bgp->advertise_all_vni)
|
||||||
bgp_config_write_family_header(vty, afi, safi, write);
|
|
||||||
vty_out(vty, " advertise-all-vni\n");
|
vty_out(vty, " advertise-all-vni\n");
|
||||||
}
|
|
||||||
|
|
||||||
if (bgp->advertise_gw_macip) {
|
if (bgp->advertise_gw_macip)
|
||||||
bgp_config_write_family_header(vty, afi, safi, write);
|
|
||||||
vty_out(vty, " advertise-default-gw\n");
|
vty_out(vty, " advertise-default-gw\n");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void bgp_ethernetvpn_init(void)
|
void bgp_ethernetvpn_init(void)
|
||||||
{
|
{
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#define _FRR_BGP_EVPN_VTY_H
|
#define _FRR_BGP_EVPN_VTY_H
|
||||||
|
|
||||||
extern void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp,
|
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);
|
extern void bgp_ethernetvpn_init(void);
|
||||||
|
|
||||||
#define L2VPN_HELP_STR "Layer 2 Virtual Private Network\n"
|
#define L2VPN_HELP_STR "Layer 2 Virtual Private Network\n"
|
||||||
|
385
bgpd/bgp_route.c
385
bgpd/bgp_route.c
@ -3397,16 +3397,18 @@ static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
|
|||||||
|
|
||||||
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
|
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
|
||||||
for (ain = rn->adj_in; ain; ain = ain->next) {
|
for (ain = rn->adj_in; ain; ain = ain->next) {
|
||||||
if (ain->peer == peer) {
|
if (ain->peer != peer)
|
||||||
|
continue;
|
||||||
|
|
||||||
struct bgp_info *ri = rn->info;
|
struct bgp_info *ri = rn->info;
|
||||||
mpls_label_t label =
|
mpls_label_t label =
|
||||||
(ri && ri->extra) ? ri->extra->label
|
(ri && ri->extra) ? ri->extra->label
|
||||||
: MPLS_INVALID_LABEL;
|
: MPLS_INVALID_LABEL;
|
||||||
|
|
||||||
ret = bgp_update(
|
ret = bgp_update(peer, &rn->p, ain->addpath_rx_id,
|
||||||
peer, &rn->p, ain->addpath_rx_id,
|
|
||||||
ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
|
ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
|
||||||
BGP_ROUTE_NORMAL, prd, &label, 1, NULL);
|
BGP_ROUTE_NORMAL, prd, &label, 1,
|
||||||
|
NULL);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
bgp_unlock_node(rn);
|
bgp_unlock_node(rn);
|
||||||
@ -3414,7 +3416,6 @@ static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
|
void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
|
||||||
{
|
{
|
||||||
@ -3460,8 +3461,10 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
|
|||||||
/* It is possible that we have multiple paths for a prefix from a peer
|
/* It is possible that we have multiple paths for a prefix from a peer
|
||||||
* if that peer is using AddPath.
|
* if that peer is using AddPath.
|
||||||
*/
|
*/
|
||||||
for (ri = rn->info; ri; ri = ri->next)
|
for (ri = rn->info; ri; ri = ri->next) {
|
||||||
if (ri->peer == peer) {
|
if (ri->peer != peer)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* graceful restart STALE flag set. */
|
/* graceful restart STALE flag set. */
|
||||||
if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
|
if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
|
||||||
&& peer->nsf[afi][safi]
|
&& peer->nsf[afi][safi]
|
||||||
@ -3472,9 +3475,8 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
|
|||||||
/* If this is an EVPN route, process for
|
/* If this is an EVPN route, process for
|
||||||
* un-import. */
|
* un-import. */
|
||||||
if (safi == SAFI_EVPN)
|
if (safi == SAFI_EVPN)
|
||||||
bgp_evpn_unimport_route(peer->bgp, afi,
|
bgp_evpn_unimport_route(peer->bgp, afi, safi,
|
||||||
safi, &rn->p,
|
&rn->p, ri);
|
||||||
ri);
|
|
||||||
bgp_rib_remove(rn, ri, peer, afi, safi);
|
bgp_rib_remove(rn, ri, peer, afi, safi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3711,32 +3713,31 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
|
|||||||
struct bgp_info *ri;
|
struct bgp_info *ri;
|
||||||
|
|
||||||
/* look for neighbor in tables */
|
/* look for neighbor in tables */
|
||||||
if ((table = rn->info) != NULL) {
|
if ((table = rn->info) == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
for (rm = bgp_table_top(table); rm;
|
for (rm = bgp_table_top(table); rm;
|
||||||
rm = bgp_route_next(rm))
|
rm = bgp_route_next(rm))
|
||||||
for (ri = rm->info; ri; ri = ri->next)
|
for (ri = rm->info; ri; ri = ri->next) {
|
||||||
if (ri->peer == peer) {
|
if (ri->peer != peer)
|
||||||
if (CHECK_FLAG(
|
continue;
|
||||||
ri->flags,
|
if (!CHECK_FLAG(ri->flags,
|
||||||
BGP_INFO_STALE))
|
BGP_INFO_STALE))
|
||||||
bgp_rib_remove(
|
|
||||||
rm, ri,
|
|
||||||
peer,
|
|
||||||
afi,
|
|
||||||
safi);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
bgp_rib_remove(rm, ri, peer, afi, safi);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
|
for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
|
||||||
rn = bgp_route_next(rn))
|
rn = bgp_route_next(rn))
|
||||||
for (ri = rn->info; ri; ri = ri->next)
|
for (ri = rn->info; ri; ri = ri->next) {
|
||||||
if (ri->peer == peer) {
|
if (ri->peer != peer)
|
||||||
if (CHECK_FLAG(ri->flags,
|
continue;
|
||||||
BGP_INFO_STALE))
|
if (!CHECK_FLAG(ri->flags, BGP_INFO_STALE))
|
||||||
bgp_rib_remove(rn, ri, peer,
|
break;
|
||||||
afi, safi);
|
bgp_rib_remove(rn, ri, peer, afi, safi);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4562,8 +4563,10 @@ void bgp_static_add(struct bgp *bgp)
|
|||||||
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
||||||
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
|
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
|
||||||
for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
|
for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
|
||||||
rn = bgp_route_next(rn))
|
rn = bgp_route_next(rn)) {
|
||||||
if (rn->info != NULL) {
|
if (rn->info == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
if ((safi == SAFI_MPLS_VPN)
|
if ((safi == SAFI_MPLS_VPN)
|
||||||
|| (safi == SAFI_ENCAP)
|
|| (safi == SAFI_ENCAP)
|
||||||
|| (safi == SAFI_EVPN)) {
|
|| (safi == SAFI_EVPN)) {
|
||||||
@ -4600,8 +4603,10 @@ void bgp_static_delete(struct bgp *bgp)
|
|||||||
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
||||||
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
|
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
|
||||||
for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
|
for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
|
||||||
rn = bgp_route_next(rn))
|
rn = bgp_route_next(rn)) {
|
||||||
if (rn->info != NULL) {
|
if (rn->info == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
if ((safi == SAFI_MPLS_VPN)
|
if ((safi == SAFI_MPLS_VPN)
|
||||||
|| (safi == SAFI_ENCAP)
|
|| (safi == SAFI_ENCAP)
|
||||||
|| (safi == SAFI_EVPN)) {
|
|| (safi == SAFI_EVPN)) {
|
||||||
@ -4617,8 +4622,7 @@ void bgp_static_delete(struct bgp *bgp)
|
|||||||
(struct
|
(struct
|
||||||
prefix_rd *)&rn
|
prefix_rd *)&rn
|
||||||
->p);
|
->p);
|
||||||
bgp_static_free(
|
bgp_static_free(bgp_static);
|
||||||
bgp_static);
|
|
||||||
rn->info = NULL;
|
rn->info = NULL;
|
||||||
bgp_unlock_node(rn);
|
bgp_unlock_node(rn);
|
||||||
}
|
}
|
||||||
@ -4647,8 +4651,10 @@ void bgp_static_redo_import_check(struct bgp *bgp)
|
|||||||
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
||||||
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
|
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
|
||||||
for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
|
for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
|
||||||
rn = bgp_route_next(rn))
|
rn = bgp_route_next(rn)) {
|
||||||
if (rn->info != NULL) {
|
if (rn->info == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
if ((safi == SAFI_MPLS_VPN)
|
if ((safi == SAFI_MPLS_VPN)
|
||||||
|| (safi == SAFI_ENCAP)
|
|| (safi == SAFI_ENCAP)
|
||||||
|| (safi == SAFI_EVPN)) {
|
|| (safi == SAFI_EVPN)) {
|
||||||
@ -4953,16 +4959,13 @@ static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
|
void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||||
safi_t safi, int *write)
|
safi_t safi)
|
||||||
{
|
{
|
||||||
if (bgp->table_map[afi][safi].name) {
|
if (bgp->table_map[afi][safi].name) {
|
||||||
bgp_config_write_family_header(vty, afi, safi, write);
|
|
||||||
vty_out(vty, " table-map %s\n",
|
vty_out(vty, " table-map %s\n",
|
||||||
bgp->table_map[afi][safi].name);
|
bgp->table_map[afi][safi].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN (bgp_table_map,
|
DEFUN (bgp_table_map,
|
||||||
@ -5693,8 +5696,10 @@ static void bgp_aggregate_add(struct bgp *bgp, struct prefix *p, afi_t afi,
|
|||||||
/* If routes exists below this node, generate aggregate routes. */
|
/* If routes exists below this node, generate aggregate routes. */
|
||||||
top = bgp_node_get(table, p);
|
top = bgp_node_get(table, p);
|
||||||
for (rn = bgp_node_get(table, p); rn;
|
for (rn = bgp_node_get(table, p); rn;
|
||||||
rn = bgp_route_next_until(rn, top))
|
rn = bgp_route_next_until(rn, top)) {
|
||||||
if (rn->p.prefixlen > p->prefixlen) {
|
if (rn->p.prefixlen <= p->prefixlen)
|
||||||
|
continue;
|
||||||
|
|
||||||
match = 0;
|
match = 0;
|
||||||
|
|
||||||
for (ri = rn->info; ri; ri = ri->next) {
|
for (ri = rn->info; ri; ri = ri->next) {
|
||||||
@ -5705,48 +5710,40 @@ static void bgp_aggregate_add(struct bgp *bgp, struct prefix *p, afi_t afi,
|
|||||||
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
|
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
|
||||||
atomic_aggregate = 1;
|
atomic_aggregate = 1;
|
||||||
|
|
||||||
if (ri->sub_type != BGP_ROUTE_AGGREGATE) {
|
if (ri->sub_type == BGP_ROUTE_AGGREGATE)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* summary-only aggregate route suppress
|
/* summary-only aggregate route suppress
|
||||||
aggregated
|
* aggregated route announcement. */
|
||||||
route announcement. */
|
|
||||||
if (aggregate->summary_only) {
|
if (aggregate->summary_only) {
|
||||||
(bgp_info_extra_get(ri))
|
(bgp_info_extra_get(ri))->suppress++;
|
||||||
->suppress++;
|
bgp_info_set_flag(rn, ri,
|
||||||
bgp_info_set_flag(
|
|
||||||
rn, ri,
|
|
||||||
BGP_INFO_ATTR_CHANGED);
|
BGP_INFO_ATTR_CHANGED);
|
||||||
match++;
|
match++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If at least one route among routes
|
/* If at least one route among routes that are
|
||||||
* that are aggregated has
|
* aggregated has ORIGIN with the value INCOMPLETE,
|
||||||
* ORIGIN with the value INCOMPLETE,
|
* then the aggregated route MUST have the ORIGIN
|
||||||
* then the aggregated route
|
* attribute with the value INCOMPLETE. Otherwise, if
|
||||||
* MUST have the ORIGIN attribute with
|
* at least one route among routes that are aggregated
|
||||||
* the value INCOMPLETE.
|
* has ORIGIN with the value EGP, then the aggregated
|
||||||
* Otherwise, if at least one route
|
* route MUST have the ORIGIN attribute with the value
|
||||||
* among routes that are
|
* EGP.
|
||||||
* aggregated has ORIGIN with the value
|
|
||||||
* EGP, then the aggregated
|
|
||||||
* route MUST have the ORIGIN attribute
|
|
||||||
* with the value EGP.
|
|
||||||
*/
|
*/
|
||||||
if (origin < ri->attr->origin)
|
if (origin < ri->attr->origin)
|
||||||
origin = ri->attr->origin;
|
origin = ri->attr->origin;
|
||||||
|
|
||||||
/* as-set aggregate route generate
|
/* as-set aggregate route generate origin, as path,
|
||||||
origin, as path,
|
* community aggregation. */
|
||||||
community aggregation. */
|
|
||||||
if (aggregate->as_set) {
|
if (aggregate->as_set) {
|
||||||
if (aspath) {
|
if (aspath) {
|
||||||
asmerge = aspath_aggregate(
|
asmerge = aspath_aggregate(aspath,
|
||||||
aspath,
|
|
||||||
ri->attr->aspath);
|
ri->attr->aspath);
|
||||||
aspath_free(aspath);
|
aspath_free(aspath);
|
||||||
aspath = asmerge;
|
aspath = asmerge;
|
||||||
} else
|
} else
|
||||||
aspath = aspath_dup(
|
aspath = aspath_dup(ri->attr->aspath);
|
||||||
ri->attr->aspath);
|
|
||||||
|
|
||||||
if (ri->attr->community) {
|
if (ri->attr->community) {
|
||||||
if (community) {
|
if (community) {
|
||||||
@ -5764,7 +5761,6 @@ static void bgp_aggregate_add(struct bgp *bgp, struct prefix *p, afi_t afi,
|
|||||||
}
|
}
|
||||||
aggregate->count++;
|
aggregate->count++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* If this node is suppressed, process the change. */
|
/* If this node is suppressed, process the change. */
|
||||||
if (match)
|
if (match)
|
||||||
@ -5815,29 +5811,29 @@ void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
|
|||||||
/* If routes exists below this node, generate aggregate routes. */
|
/* If routes exists below this node, generate aggregate routes. */
|
||||||
top = bgp_node_get(table, p);
|
top = bgp_node_get(table, p);
|
||||||
for (rn = bgp_node_get(table, p); rn;
|
for (rn = bgp_node_get(table, p); rn;
|
||||||
rn = bgp_route_next_until(rn, top))
|
rn = bgp_route_next_until(rn, top)) {
|
||||||
if (rn->p.prefixlen > p->prefixlen) {
|
if (rn->p.prefixlen <= p->prefixlen)
|
||||||
|
continue;
|
||||||
match = 0;
|
match = 0;
|
||||||
|
|
||||||
for (ri = rn->info; ri; ri = ri->next) {
|
for (ri = rn->info; ri; ri = ri->next) {
|
||||||
if (BGP_INFO_HOLDDOWN(ri))
|
if (BGP_INFO_HOLDDOWN(ri))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (ri->sub_type != BGP_ROUTE_AGGREGATE) {
|
if (ri->sub_type == BGP_ROUTE_AGGREGATE)
|
||||||
if (aggregate->summary_only
|
continue;
|
||||||
&& ri->extra) {
|
|
||||||
|
if (aggregate->summary_only && ri->extra) {
|
||||||
ri->extra->suppress--;
|
ri->extra->suppress--;
|
||||||
|
|
||||||
if (ri->extra->suppress == 0) {
|
if (ri->extra->suppress == 0) {
|
||||||
bgp_info_set_flag(
|
bgp_info_set_flag(rn, ri,
|
||||||
rn, ri,
|
|
||||||
BGP_INFO_ATTR_CHANGED);
|
BGP_INFO_ATTR_CHANGED);
|
||||||
match++;
|
match++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aggregate->count--;
|
aggregate->count--;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* If this node was suppressed, process the change. */
|
/* If this node was suppressed, process the change. */
|
||||||
if (match)
|
if (match)
|
||||||
@ -8591,56 +8587,45 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
|
|||||||
if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
|
if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((table = rn->info) != NULL) {
|
if ((table = rn->info) == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
header = 1;
|
header = 1;
|
||||||
|
|
||||||
if ((rm = bgp_node_match(table, &match))
|
if ((rm = bgp_node_match(table, &match)) == NULL)
|
||||||
!= NULL) {
|
continue;
|
||||||
|
|
||||||
if (prefix_check
|
if (prefix_check
|
||||||
&& rm->p.prefixlen
|
&& rm->p.prefixlen != match.prefixlen) {
|
||||||
!= match.prefixlen) {
|
|
||||||
bgp_unlock_node(rm);
|
bgp_unlock_node(rm);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ri = rm->info; ri; ri = ri->next) {
|
for (ri = rm->info; ri; ri = ri->next) {
|
||||||
if (header) {
|
if (header) {
|
||||||
route_vty_out_detail_header(
|
route_vty_out_detail_header(vty, bgp,
|
||||||
vty, bgp, rm,
|
rm, (struct prefix_rd *)&rn->p,
|
||||||
(struct
|
AFI_IP, safi, json);
|
||||||
prefix_rd *)&rn
|
|
||||||
->p,
|
|
||||||
AFI_IP, safi,
|
|
||||||
json);
|
|
||||||
header = 0;
|
header = 0;
|
||||||
}
|
}
|
||||||
display++;
|
display++;
|
||||||
|
|
||||||
if (pathtype == BGP_PATH_ALL
|
if (pathtype == BGP_PATH_ALL
|
||||||
|| (pathtype
|
|| (pathtype == BGP_PATH_BESTPATH
|
||||||
== BGP_PATH_BESTPATH
|
&& CHECK_FLAG(ri->flags,
|
||||||
&& CHECK_FLAG(
|
|
||||||
ri->flags,
|
|
||||||
BGP_INFO_SELECTED))
|
BGP_INFO_SELECTED))
|
||||||
|| (pathtype
|
|| (pathtype == BGP_PATH_MULTIPATH
|
||||||
== BGP_PATH_MULTIPATH
|
&& (CHECK_FLAG(ri->flags,
|
||||||
&& (CHECK_FLAG(
|
|
||||||
ri->flags,
|
|
||||||
BGP_INFO_MULTIPATH)
|
BGP_INFO_MULTIPATH)
|
||||||
|| CHECK_FLAG(
|
|| CHECK_FLAG(ri->flags,
|
||||||
ri->flags,
|
|
||||||
BGP_INFO_SELECTED))))
|
BGP_INFO_SELECTED))))
|
||||||
route_vty_out_detail(
|
route_vty_out_detail(vty, bgp, &rm->p,
|
||||||
vty, bgp,
|
ri, AFI_IP, safi,
|
||||||
&rm->p, ri,
|
|
||||||
AFI_IP, safi,
|
|
||||||
json_paths);
|
json_paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
bgp_unlock_node(rm);
|
bgp_unlock_node(rm);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
header = 1;
|
header = 1;
|
||||||
|
|
||||||
@ -10025,7 +10010,8 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
|
|||||||
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
|
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
|
||||||
if (in) {
|
if (in) {
|
||||||
for (ain = rn->adj_in; ain; ain = ain->next) {
|
for (ain = rn->adj_in; ain; ain = ain->next) {
|
||||||
if (ain->peer == peer) {
|
if (ain->peer != peer)
|
||||||
|
continue;
|
||||||
if (header1) {
|
if (header1) {
|
||||||
if (use_json) {
|
if (use_json) {
|
||||||
json_object_int_add(
|
json_object_int_add(
|
||||||
@ -10059,28 +10045,22 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
|
|||||||
}
|
}
|
||||||
if (header2) {
|
if (header2) {
|
||||||
if (!use_json)
|
if (!use_json)
|
||||||
vty_out(vty,
|
vty_out(vty, BGP_SHOW_HEADER);
|
||||||
BGP_SHOW_HEADER);
|
|
||||||
header2 = 0;
|
header2 = 0;
|
||||||
}
|
}
|
||||||
if (ain->attr) {
|
if (ain->attr) {
|
||||||
bgp_attr_dup(&attr, ain->attr);
|
bgp_attr_dup(&attr, ain->attr);
|
||||||
if (bgp_input_modifier(
|
if (bgp_input_modifier(peer, &rn->p,
|
||||||
peer, &rn->p, &attr,
|
&attr, afi, safi, rmap_name)
|
||||||
afi, safi,
|
|
||||||
rmap_name)
|
|
||||||
!= RMAP_DENY) {
|
!= RMAP_DENY) {
|
||||||
route_vty_out_tmp(
|
route_vty_out_tmp(vty, &rn->p,
|
||||||
vty, &rn->p,
|
&attr, safi, use_json,
|
||||||
&attr, safi,
|
|
||||||
use_json,
|
|
||||||
json_ar);
|
json_ar);
|
||||||
output_count++;
|
output_count++;
|
||||||
} else
|
} else
|
||||||
filtered_count++;
|
filtered_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
for (adj = rn->adj_out; adj; adj = adj->next)
|
for (adj = rn->adj_out; adj; adj = adj->next)
|
||||||
SUBGRP_FOREACH_PEER(adj->subgroup, paf)
|
SUBGRP_FOREACH_PEER(adj->subgroup, paf)
|
||||||
@ -10886,24 +10866,20 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
|
|||||||
rn = bgp_route_next(rn)) {
|
rn = bgp_route_next(rn)) {
|
||||||
if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
|
if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
if ((table = rn->info) == NULL)
|
||||||
|
continue;
|
||||||
|
if ((rm = bgp_node_match(table, &match)) == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
if ((table = rn->info) != NULL)
|
|
||||||
if ((rm = bgp_node_match(table, &match))
|
|
||||||
!= NULL) {
|
|
||||||
if (!prefix_check
|
if (!prefix_check
|
||||||
|| rm->p.prefixlen
|
|| rm->p.prefixlen == match.prefixlen) {
|
||||||
== match.prefixlen) {
|
|
||||||
ri = rm->info;
|
ri = rm->info;
|
||||||
while (ri) {
|
while (ri) {
|
||||||
if (ri->extra
|
if (ri->extra
|
||||||
&& ri->extra
|
&& ri->extra->damp_info) {
|
||||||
->damp_info) {
|
ri_temp = ri->next;
|
||||||
ri_temp =
|
|
||||||
ri->next;
|
|
||||||
bgp_damp_info_free(
|
bgp_damp_info_free(
|
||||||
ri->extra
|
ri->extra->damp_info, 1);
|
||||||
->damp_info,
|
|
||||||
1);
|
|
||||||
ri = ri_temp;
|
ri = ri_temp;
|
||||||
} else
|
} else
|
||||||
ri = ri->next;
|
ri = ri->next;
|
||||||
@ -10912,7 +10888,6 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
|
|||||||
|
|
||||||
bgp_unlock_node(rm);
|
bgp_unlock_node(rm);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
|
if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
|
||||||
!= NULL) {
|
!= NULL) {
|
||||||
@ -11005,8 +10980,8 @@ DEFUN (clear_ip_bgp_dampening_address_mask,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* also used for encap safi */
|
/* also used for encap safi */
|
||||||
static int bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
|
static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
|
||||||
afi_t afi, safi_t safi, int *write)
|
afi_t afi, safi_t safi)
|
||||||
{
|
{
|
||||||
struct bgp_node *prn;
|
struct bgp_node *prn;
|
||||||
struct bgp_node *rn;
|
struct bgp_node *rn;
|
||||||
@ -11020,48 +10995,43 @@ static int bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
|
|||||||
|
|
||||||
/* Network configuration. */
|
/* Network configuration. */
|
||||||
for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
|
for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
|
||||||
prn = bgp_route_next(prn))
|
prn = bgp_route_next(prn)) {
|
||||||
if ((table = prn->info) != NULL)
|
if ((table = prn->info) == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
for (rn = bgp_table_top(table); rn;
|
for (rn = bgp_table_top(table); rn;
|
||||||
rn = bgp_route_next(rn))
|
rn = bgp_route_next(rn)) {
|
||||||
if ((bgp_static = rn->info) != NULL) {
|
if ((bgp_static = rn->info) == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
p = &rn->p;
|
p = &rn->p;
|
||||||
prd = (struct prefix_rd *)&prn->p;
|
prd = (struct prefix_rd *)&prn->p;
|
||||||
|
|
||||||
/* "address-family" display. */
|
|
||||||
bgp_config_write_family_header(
|
|
||||||
vty, afi, safi, write);
|
|
||||||
|
|
||||||
/* "network" configuration display. */
|
/* "network" configuration display. */
|
||||||
prefix_rd2str(prd, rdbuf,
|
prefix_rd2str(prd, rdbuf, RD_ADDRSTRLEN);
|
||||||
RD_ADDRSTRLEN);
|
label = decode_label(&bgp_static->label);
|
||||||
label = decode_label(
|
|
||||||
&bgp_static->label);
|
|
||||||
|
|
||||||
vty_out(vty, " network %s/%d rd %s",
|
vty_out(vty, " network %s/%d rd %s",
|
||||||
inet_ntop(p->family,
|
inet_ntop(p->family, &p->u.prefix, buf,
|
||||||
&p->u.prefix, buf,
|
|
||||||
SU_ADDRSTRLEN),
|
SU_ADDRSTRLEN),
|
||||||
p->prefixlen, rdbuf);
|
p->prefixlen, rdbuf);
|
||||||
if (safi == SAFI_MPLS_VPN)
|
if (safi == SAFI_MPLS_VPN)
|
||||||
vty_out(vty, " label %u",
|
vty_out(vty, " label %u", label);
|
||||||
label);
|
|
||||||
|
|
||||||
if (bgp_static->rmap.name)
|
if (bgp_static->rmap.name)
|
||||||
vty_out(vty, " route-map %s",
|
vty_out(vty, " route-map %s",
|
||||||
bgp_static->rmap.name);
|
bgp_static->rmap.name);
|
||||||
else {
|
else {
|
||||||
if (bgp_static->backdoor)
|
if (bgp_static->backdoor)
|
||||||
vty_out(vty,
|
vty_out(vty, " backdoor");
|
||||||
" backdoor");
|
|
||||||
}
|
}
|
||||||
vty_out(vty, "\n");
|
vty_out(vty, "\n");
|
||||||
}
|
}
|
||||||
return 0;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
|
static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
|
||||||
afi_t afi, safi_t safi, int *write)
|
afi_t afi, safi_t safi)
|
||||||
{
|
{
|
||||||
struct bgp_node *prn;
|
struct bgp_node *prn;
|
||||||
struct bgp_node *rn;
|
struct bgp_node *rn;
|
||||||
@ -11075,59 +11045,51 @@ static int bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
|
|||||||
|
|
||||||
/* Network configuration. */
|
/* Network configuration. */
|
||||||
for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
|
for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
|
||||||
prn = bgp_route_next(prn))
|
prn = bgp_route_next(prn)) {
|
||||||
if ((table = prn->info) != NULL)
|
if ((table = prn->info) == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
for (rn = bgp_table_top(table); rn;
|
for (rn = bgp_table_top(table); rn;
|
||||||
rn = bgp_route_next(rn))
|
rn = bgp_route_next(rn)) {
|
||||||
if ((bgp_static = rn->info) != NULL) {
|
if ((bgp_static = rn->info) == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
char *macrouter = NULL;
|
char *macrouter = NULL;
|
||||||
char *esi = NULL;
|
char *esi = NULL;
|
||||||
|
|
||||||
if (bgp_static->router_mac)
|
if (bgp_static->router_mac)
|
||||||
macrouter = prefix_mac2str(
|
macrouter = prefix_mac2str(
|
||||||
bgp_static->router_mac,
|
bgp_static->router_mac, NULL, 0);
|
||||||
NULL, 0);
|
|
||||||
if (bgp_static->eth_s_id)
|
if (bgp_static->eth_s_id)
|
||||||
esi = esi2str(
|
esi = esi2str(bgp_static->eth_s_id);
|
||||||
bgp_static->eth_s_id);
|
|
||||||
p = &rn->p;
|
p = &rn->p;
|
||||||
prd = (struct prefix_rd *)&prn->p;
|
prd = (struct prefix_rd *)&prn->p;
|
||||||
|
|
||||||
/* "address-family" display. */
|
|
||||||
bgp_config_write_family_header(
|
|
||||||
vty, afi, safi, write);
|
|
||||||
|
|
||||||
/* "network" configuration display. */
|
/* "network" configuration display. */
|
||||||
prefix_rd2str(prd, rdbuf,
|
prefix_rd2str(prd, rdbuf, RD_ADDRSTRLEN);
|
||||||
RD_ADDRSTRLEN);
|
|
||||||
|
|
||||||
inet_ntop(AF_INET,
|
inet_ntop(AF_INET, &bgp_static->igpnexthop, buf2,
|
||||||
&bgp_static->igpnexthop, buf2,
|
|
||||||
SU_ADDRSTRLEN);
|
SU_ADDRSTRLEN);
|
||||||
|
|
||||||
prefix2str(p, buf, sizeof(buf)),
|
prefix2str(p, buf, sizeof(buf));
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
" network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s",
|
" network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s\n",
|
||||||
buf, rdbuf,
|
buf, rdbuf, p->u.prefix_evpn .eth_tag,
|
||||||
p->u.prefix_evpn
|
decode_label(&bgp_static ->label), esi, buf2,
|
||||||
.eth_tag,
|
macrouter);
|
||||||
decode_label(
|
|
||||||
&bgp_static
|
|
||||||
->label),
|
|
||||||
esi, buf2, macrouter);
|
|
||||||
vty_out(vty, "\n");
|
|
||||||
if (macrouter)
|
if (macrouter)
|
||||||
XFREE(MTYPE_TMP, macrouter);
|
XFREE(MTYPE_TMP, macrouter);
|
||||||
if (esi)
|
if (esi)
|
||||||
XFREE(MTYPE_TMP, esi);
|
XFREE(MTYPE_TMP, esi);
|
||||||
}
|
}
|
||||||
return 0;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Configuration of static route announcement and aggregate
|
/* Configuration of static route announcement and aggregate
|
||||||
information. */
|
information. */
|
||||||
int bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
|
void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||||
safi_t safi, int *write)
|
safi_t safi)
|
||||||
{
|
{
|
||||||
struct bgp_node *rn;
|
struct bgp_node *rn;
|
||||||
struct prefix *p;
|
struct prefix *p;
|
||||||
@ -11135,21 +11097,23 @@ int bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
|
|||||||
struct bgp_aggregate *bgp_aggregate;
|
struct bgp_aggregate *bgp_aggregate;
|
||||||
char buf[SU_ADDRSTRLEN];
|
char buf[SU_ADDRSTRLEN];
|
||||||
|
|
||||||
if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
|
if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
|
||||||
return bgp_config_write_network_vpn(vty, bgp, afi, safi, write);
|
bgp_config_write_network_vpn(vty, bgp, afi, safi);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (afi == AFI_L2VPN && safi == SAFI_EVPN)
|
if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
|
||||||
return bgp_config_write_network_evpn(vty, bgp, afi, safi,
|
bgp_config_write_network_evpn(vty, bgp, afi, safi);
|
||||||
write);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Network configuration. */
|
/* Network configuration. */
|
||||||
for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
|
for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
|
||||||
rn = bgp_route_next(rn))
|
rn = bgp_route_next(rn)) {
|
||||||
if ((bgp_static = rn->info) != NULL) {
|
if ((bgp_static = rn->info) == NULL)
|
||||||
p = &rn->p;
|
continue;
|
||||||
|
|
||||||
/* "address-family" display. */
|
p = &rn->p;
|
||||||
bgp_config_write_family_header(vty, afi, safi, write);
|
|
||||||
|
|
||||||
/* "network" configuration display. */
|
/* "network" configuration display. */
|
||||||
if (bgp_option_check(BGP_OPT_CONFIG_CISCO)
|
if (bgp_option_check(BGP_OPT_CONFIG_CISCO)
|
||||||
@ -11163,17 +11127,13 @@ int bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
|
|||||||
inet_ntop(p->family, &p->u.prefix, buf,
|
inet_ntop(p->family, &p->u.prefix, buf,
|
||||||
SU_ADDRSTRLEN));
|
SU_ADDRSTRLEN));
|
||||||
|
|
||||||
if ((IN_CLASSC(destination)
|
if ((IN_CLASSC(destination) && p->prefixlen == 24)
|
||||||
&& p->prefixlen == 24)
|
|| (IN_CLASSB(destination) && p->prefixlen == 16)
|
||||||
|| (IN_CLASSB(destination)
|
|| (IN_CLASSA(destination) && p->prefixlen == 8)
|
||||||
&& p->prefixlen == 16)
|
|
||||||
|| (IN_CLASSA(destination)
|
|
||||||
&& p->prefixlen == 8)
|
|
||||||
|| p->u.prefix4.s_addr == 0) {
|
|| p->u.prefix4.s_addr == 0) {
|
||||||
/* Natural mask is not display. */
|
/* Natural mask is not display. */
|
||||||
} else
|
} else
|
||||||
vty_out(vty, " mask %s",
|
vty_out(vty, " mask %s", inet_ntoa(netmask));
|
||||||
inet_ntoa(netmask));
|
|
||||||
} else {
|
} else {
|
||||||
vty_out(vty, " network %s/%d",
|
vty_out(vty, " network %s/%d",
|
||||||
inet_ntop(p->family, &p->u.prefix, buf,
|
inet_ntop(p->family, &p->u.prefix, buf,
|
||||||
@ -11186,8 +11146,7 @@ int bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
|
|||||||
bgp_static->label_index);
|
bgp_static->label_index);
|
||||||
|
|
||||||
if (bgp_static->rmap.name)
|
if (bgp_static->rmap.name)
|
||||||
vty_out(vty, " route-map %s",
|
vty_out(vty, " route-map %s", bgp_static->rmap.name);
|
||||||
bgp_static->rmap.name);
|
|
||||||
else {
|
else {
|
||||||
if (bgp_static->backdoor)
|
if (bgp_static->backdoor)
|
||||||
vty_out(vty, " backdoor");
|
vty_out(vty, " backdoor");
|
||||||
@ -11198,15 +11157,13 @@ int bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
|
|||||||
|
|
||||||
/* Aggregate-address configuration. */
|
/* Aggregate-address configuration. */
|
||||||
for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
|
for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
|
||||||
rn = bgp_route_next(rn))
|
rn = bgp_route_next(rn)) {
|
||||||
if ((bgp_aggregate = rn->info) != NULL) {
|
if ((bgp_aggregate = rn->info) == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
p = &rn->p;
|
p = &rn->p;
|
||||||
|
|
||||||
/* "address-family" display. */
|
if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) {
|
||||||
bgp_config_write_family_header(vty, afi, safi, write);
|
|
||||||
|
|
||||||
if (bgp_option_check(BGP_OPT_CONFIG_CISCO)
|
|
||||||
&& afi == AFI_IP) {
|
|
||||||
struct in_addr netmask;
|
struct in_addr netmask;
|
||||||
|
|
||||||
masklen2ip(p->prefixlen, &netmask);
|
masklen2ip(p->prefixlen, &netmask);
|
||||||
@ -11229,12 +11186,10 @@ int bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
|
|||||||
|
|
||||||
vty_out(vty, "\n");
|
vty_out(vty, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
|
void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||||
safi_t safi, int *write)
|
safi_t safi)
|
||||||
{
|
{
|
||||||
struct bgp_node *rn;
|
struct bgp_node *rn;
|
||||||
struct bgp_distance *bdistance;
|
struct bgp_distance *bdistance;
|
||||||
@ -11246,7 +11201,6 @@ int bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
|
|||||||
|| bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
|
|| bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
|
||||||
|| bgp->distance_local[afi][safi]
|
|| bgp->distance_local[afi][safi]
|
||||||
!= ZEBRA_IBGP_DISTANCE_DEFAULT)) {
|
!= ZEBRA_IBGP_DISTANCE_DEFAULT)) {
|
||||||
bgp_config_write_family_header(vty, afi, safi, write);
|
|
||||||
vty_out(vty, " distance bgp %d %d %d\n",
|
vty_out(vty, " distance bgp %d %d %d\n",
|
||||||
bgp->distance_ebgp[afi][safi],
|
bgp->distance_ebgp[afi][safi],
|
||||||
bgp->distance_ibgp[afi][safi],
|
bgp->distance_ibgp[afi][safi],
|
||||||
@ -11258,15 +11212,12 @@ int bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
|
|||||||
if ((bdistance = rn->info) != NULL) {
|
if ((bdistance = rn->info) != NULL) {
|
||||||
char buf[PREFIX_STRLEN];
|
char buf[PREFIX_STRLEN];
|
||||||
|
|
||||||
bgp_config_write_family_header(vty, afi, safi, write);
|
|
||||||
vty_out(vty, " distance %d %s %s\n",
|
vty_out(vty, " distance %d %s %s\n",
|
||||||
bdistance->distance,
|
bdistance->distance,
|
||||||
prefix2str(&rn->p, buf, sizeof(buf)),
|
prefix2str(&rn->p, buf, sizeof(buf)),
|
||||||
bdistance->access_list ? bdistance->access_list
|
bdistance->access_list ? bdistance->access_list
|
||||||
: "");
|
: "");
|
||||||
}
|
}
|
||||||
|
|
||||||
return *write;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate routing table structure and install commands. */
|
/* Allocate routing table structure and install commands. */
|
||||||
|
@ -369,12 +369,9 @@ extern void bgp_process(struct bgp *, struct bgp_node *, afi_t, safi_t);
|
|||||||
* queue element with NULL bgp node.
|
* queue element with NULL bgp node.
|
||||||
*/
|
*/
|
||||||
extern void bgp_add_eoiu_mark(struct bgp *);
|
extern void bgp_add_eoiu_mark(struct bgp *);
|
||||||
extern int bgp_config_write_table_map(struct vty *, struct bgp *, afi_t, safi_t,
|
extern void bgp_config_write_table_map(struct vty *, struct bgp *, afi_t, safi_t);
|
||||||
int *);
|
extern void bgp_config_write_network(struct vty *, struct bgp *, afi_t, safi_t);
|
||||||
extern int 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);
|
||||||
int *);
|
|
||||||
extern int bgp_config_write_distance(struct vty *, struct bgp *, afi_t, safi_t,
|
|
||||||
int *);
|
|
||||||
|
|
||||||
extern void bgp_aggregate_increment(struct bgp *, struct prefix *,
|
extern void bgp_aggregate_increment(struct bgp *, struct prefix *,
|
||||||
struct bgp_info *, afi_t, safi_t);
|
struct bgp_info *, afi_t, safi_t);
|
||||||
|
@ -1279,7 +1279,7 @@ static int bgp_update_delay_deconfig_vty(struct vty *vty)
|
|||||||
return CMD_SUCCESS;
|
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) {
|
if (bgp->v_update_delay != BGP_UPDATE_DELAY_DEF) {
|
||||||
vty_out(vty, " update-delay %d", bgp->v_update_delay);
|
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, " %d", bgp->v_establish_wait);
|
||||||
vty_out(vty, "\n");
|
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;
|
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)
|
if (bgp->wpkt_quanta != BGP_WRITE_PACKET_MAX)
|
||||||
vty_out(vty, " write-quanta %d\n", bgp->wpkt_quanta);
|
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);
|
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)
|
if (bgp->coalesce_time != BGP_DEFAULT_SUBGROUP_COALESCE_TIME)
|
||||||
vty_out(vty, " coalesce-time %u\n", bgp->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"
|
"Number of paths\n"
|
||||||
"Match the cluster length\n")
|
"Match the cluster length\n")
|
||||||
|
|
||||||
int bgp_config_write_maxpaths(struct vty *vty, struct bgp *bgp, afi_t afi,
|
void bgp_config_write_maxpaths(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||||
safi_t safi, int *write)
|
safi_t safi)
|
||||||
{
|
{
|
||||||
if (bgp->maxpaths[afi][safi].maxpaths_ebgp != MULTIPATH_NUM) {
|
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",
|
vty_out(vty, " maximum-paths %d\n",
|
||||||
bgp->maxpaths[afi][safi].maxpaths_ebgp);
|
bgp->maxpaths[afi][safi].maxpaths_ebgp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bgp->maxpaths[afi][safi].maxpaths_ibgp != MULTIPATH_NUM) {
|
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",
|
vty_out(vty, " maximum-paths ibgp %d",
|
||||||
bgp->maxpaths[afi][safi].maxpaths_ibgp);
|
bgp->maxpaths[afi][safi].maxpaths_ibgp);
|
||||||
if (CHECK_FLAG(bgp->maxpaths[afi][safi].ibgp_flags,
|
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, " equal-cluster-length");
|
||||||
vty_out(vty, "\n");
|
vty_out(vty, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BGP timers. */
|
/* BGP timers. */
|
||||||
@ -2459,7 +2449,7 @@ DEFUN (no_bgp_listen_range,
|
|||||||
return bgp_vty_return(vty, ret);
|
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 peer_group *group;
|
||||||
struct listnode *node, *nnode, *rnode, *nrnode;
|
struct listnode *node, *nnode, *rnode, *nrnode;
|
||||||
@ -2482,8 +2472,6 @@ int bgp_config_write_listen(struct vty *vty, struct bgp *bgp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -6675,7 +6663,9 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
|
|||||||
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
|
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (peer->afc[afi][safi]) {
|
if (!peer->afc[afi][safi])
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!count) {
|
if (!count) {
|
||||||
unsigned long ents;
|
unsigned long ents;
|
||||||
char memstrbuf[MTYPE_MEMSTR_LEN];
|
char memstrbuf[MTYPE_MEMSTR_LEN];
|
||||||
@ -7037,7 +7027,6 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
|
|||||||
vty_out(vty, "\n");
|
vty_out(vty, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (use_json) {
|
if (use_json) {
|
||||||
json_object_object_add(json, "peers", json_peers);
|
json_object_object_add(json, "peers", json_peers);
|
||||||
@ -11156,14 +11145,14 @@ DEFUN (no_bgp_redistribute_ipv6,
|
|||||||
return bgp_redistribute_unset(bgp, AFI_IP6, type, 0);
|
return bgp_redistribute_unset(bgp, AFI_IP6, type, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi,
|
void bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||||
safi_t safi, int *write)
|
safi_t safi)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Unicast redistribution only. */
|
/* Unicast redistribution only. */
|
||||||
if (safi != SAFI_UNICAST)
|
if (safi != SAFI_UNICAST)
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
||||||
/* Redistribute BGP does not make sense. */
|
/* 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;
|
continue;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
|
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. */
|
/* "redistribute" configuration. */
|
||||||
vty_out(vty, " redistribute %s",
|
vty_out(vty, " redistribute %s",
|
||||||
zebra_route_string(i));
|
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. */
|
/* BGP node structure. */
|
||||||
|
@ -46,10 +46,10 @@ struct bgp;
|
|||||||
extern void bgp_vty_init(void);
|
extern void bgp_vty_init(void);
|
||||||
extern const char *afi_safi_print(afi_t, safi_t);
|
extern const char *afi_safi_print(afi_t, safi_t);
|
||||||
extern const char *afi_safi_json(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 void bgp_config_write_update_delay(struct vty *, struct bgp *);
|
||||||
extern int bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp);
|
extern void bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp);
|
||||||
extern int bgp_config_write_listen(struct vty *vty, struct bgp *bgp);
|
extern void 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_coalesce_time(struct vty *vty, struct bgp *bgp);
|
||||||
extern int bgp_vty_return(struct vty *vty, int ret);
|
extern int bgp_vty_return(struct vty *vty, int ret);
|
||||||
extern struct peer *peer_and_group_lookup_vty(struct vty *vty,
|
extern struct peer *peer_and_group_lookup_vty(struct vty *vty,
|
||||||
const char *peer_str);
|
const char *peer_str);
|
||||||
|
@ -26,10 +26,10 @@
|
|||||||
extern void bgp_zebra_init(struct thread_master *master);
|
extern void bgp_zebra_init(struct thread_master *master);
|
||||||
extern void bgp_zebra_destroy(void);
|
extern void bgp_zebra_destroy(void);
|
||||||
extern int bgp_if_update_all(void);
|
extern int bgp_if_update_all(void);
|
||||||
extern int bgp_config_write_maxpaths(struct vty *, struct bgp *, afi_t, safi_t,
|
extern void bgp_config_write_maxpaths(struct vty *, struct bgp *, afi_t,
|
||||||
int *);
|
safi_t);
|
||||||
extern int bgp_config_write_redistribute(struct vty *, struct bgp *, afi_t,
|
extern void bgp_config_write_redistribute(struct vty *, struct bgp *, afi_t,
|
||||||
safi_t, int *);
|
safi_t);
|
||||||
extern void bgp_zebra_announce(struct bgp_node *, struct prefix *,
|
extern void bgp_zebra_announce(struct bgp_node *, struct prefix *,
|
||||||
struct bgp_info *, struct bgp *, afi_t, safi_t);
|
struct bgp_info *, struct bgp *, afi_t, safi_t);
|
||||||
extern void bgp_zebra_announce_table(struct bgp *, afi_t, safi_t);
|
extern void bgp_zebra_announce_table(struct bgp *, afi_t, safi_t);
|
||||||
|
320
bgpd/bgpd.c
320
bgpd/bgpd.c
@ -6204,14 +6204,8 @@ char *peer_uptime(time_t uptime2, char *buf, size_t len, u_char use_json,
|
|||||||
return buf;
|
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,
|
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 *filter;
|
||||||
struct bgp_filter *gfilter = NULL;
|
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
|
if (!gfilter || !gfilter->dlist[in].name
|
||||||
|| strcmp(filter->dlist[in].name, gfilter->dlist[in].name)
|
|| strcmp(filter->dlist[in].name, gfilter->dlist[in].name)
|
||||||
!= 0) {
|
!= 0) {
|
||||||
afi_header_vty_out(
|
vty_out(vty, " neighbor %s distribute-list %s in\n",
|
||||||
vty, afi, safi, write,
|
addr, filter->dlist[in].name);
|
||||||
" neighbor %s distribute-list %s in\n", addr,
|
|
||||||
filter->dlist[in].name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter->dlist[out].name && !gfilter) {
|
if (filter->dlist[out].name && !gfilter) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s distribute-list %s out\n", addr,
|
||||||
" neighbor %s distribute-list %s out\n",
|
filter->dlist[out].name);
|
||||||
addr, filter->dlist[out].name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* prefix-list. */
|
/* prefix-list. */
|
||||||
@ -6247,18 +6238,16 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
|
|||||||
if (!gfilter || !gfilter->plist[in].name
|
if (!gfilter || !gfilter->plist[in].name
|
||||||
|| strcmp(filter->plist[in].name, gfilter->plist[in].name)
|
|| strcmp(filter->plist[in].name, gfilter->plist[in].name)
|
||||||
!= 0) {
|
!= 0) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s prefix-list %s in\n", addr,
|
||||||
" neighbor %s prefix-list %s in\n",
|
filter->plist[in].name);
|
||||||
addr, filter->plist[in].name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter->plist[out].name)
|
if (filter->plist[out].name)
|
||||||
if (!gfilter || !gfilter->plist[out].name
|
if (!gfilter || !gfilter->plist[out].name
|
||||||
|| strcmp(filter->plist[out].name, gfilter->plist[out].name)
|
|| strcmp(filter->plist[out].name, gfilter->plist[out].name)
|
||||||
!= 0) {
|
!= 0) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s prefix-list %s out\n", addr,
|
||||||
" neighbor %s prefix-list %s out\n",
|
filter->plist[out].name);
|
||||||
addr, filter->plist[out].name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* route-map. */
|
/* route-map. */
|
||||||
@ -6267,9 +6256,8 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
|
|||||||
|| strcmp(filter->map[RMAP_IN].name,
|
|| strcmp(filter->map[RMAP_IN].name,
|
||||||
gfilter->map[RMAP_IN].name)
|
gfilter->map[RMAP_IN].name)
|
||||||
!= 0) {
|
!= 0) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s route-map %s in\n", addr,
|
||||||
" neighbor %s route-map %s in\n",
|
filter->map[RMAP_IN].name);
|
||||||
addr, filter->map[RMAP_IN].name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter->map[RMAP_OUT].name)
|
if (filter->map[RMAP_OUT].name)
|
||||||
@ -6277,15 +6265,13 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
|
|||||||
|| strcmp(filter->map[RMAP_OUT].name,
|
|| strcmp(filter->map[RMAP_OUT].name,
|
||||||
gfilter->map[RMAP_OUT].name)
|
gfilter->map[RMAP_OUT].name)
|
||||||
!= 0) {
|
!= 0) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s route-map %s out\n", addr,
|
||||||
" neighbor %s route-map %s out\n",
|
filter->map[RMAP_OUT].name);
|
||||||
addr, filter->map[RMAP_OUT].name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unsuppress-map */
|
/* unsuppress-map */
|
||||||
if (filter->usmap.name && !gfilter) {
|
if (filter->usmap.name && !gfilter) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s unsuppress-map %s\n", addr,
|
||||||
" neighbor %s unsuppress-map %s\n", addr,
|
|
||||||
filter->usmap.name);
|
filter->usmap.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6294,14 +6280,12 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
|
|||||||
if (!gfilter || !gfilter->aslist[in].name
|
if (!gfilter || !gfilter->aslist[in].name
|
||||||
|| strcmp(filter->aslist[in].name, gfilter->aslist[in].name)
|
|| strcmp(filter->aslist[in].name, gfilter->aslist[in].name)
|
||||||
!= 0) {
|
!= 0) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s filter-list %s in\n", addr,
|
||||||
" neighbor %s filter-list %s in\n",
|
filter->aslist[in].name);
|
||||||
addr, filter->aslist[in].name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter->aslist[out].name && !gfilter) {
|
if (filter->aslist[out].name && !gfilter) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s filter-list %s out\n", addr,
|
||||||
" neighbor %s filter-list %s out\n", addr,
|
|
||||||
filter->aslist[out].name);
|
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. */
|
/* BGP peer configuration display function. */
|
||||||
static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
||||||
struct peer *peer, afi_t afi, safi_t safi,
|
struct peer *peer, afi_t afi, safi_t safi)
|
||||||
int *write)
|
|
||||||
{
|
{
|
||||||
struct peer *g_peer = NULL;
|
struct peer *g_peer = NULL;
|
||||||
char *addr;
|
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
|
/* If the peer-group is active but peer is not, print a 'no
|
||||||
* activate' */
|
* activate' */
|
||||||
if (g_peer->afc[afi][safi] && !peer->afc[afi][safi]) {
|
if (g_peer->afc[afi][safi] && !peer->afc[afi][safi]) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " no neighbor %s activate\n", addr);
|
||||||
" no neighbor %s activate\n", addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the peer-group is not active but peer is, print an
|
/* If the peer-group is not active but peer is, print an
|
||||||
'activate' */
|
'activate' */
|
||||||
else if (!g_peer->afc[afi][safi] && peer->afc[afi][safi]) {
|
else if (!g_peer->afc[afi][safi] && peer->afc[afi][safi]) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s activate\n", addr);
|
||||||
" neighbor %s activate\n", addr);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (peer->afc[afi][safi]) {
|
if (peer->afc[afi][safi]) {
|
||||||
if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
|
if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
|
||||||
if (bgp_flag_check(bgp,
|
if (bgp_flag_check(bgp,
|
||||||
BGP_FLAG_NO_DEFAULT_IPV4)) {
|
BGP_FLAG_NO_DEFAULT_IPV4)) {
|
||||||
afi_header_vty_out(
|
vty_out(vty, " neighbor %s activate\n",
|
||||||
vty, afi, safi, write,
|
|
||||||
" neighbor %s activate\n",
|
|
||||||
addr);
|
addr);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s activate\n", addr);
|
||||||
" neighbor %s activate\n",
|
|
||||||
addr);
|
|
||||||
} else {
|
} else {
|
||||||
if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
|
if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
|
||||||
if (!bgp_flag_check(bgp,
|
if (!bgp_flag_check(bgp,
|
||||||
BGP_FLAG_NO_DEFAULT_IPV4)) {
|
BGP_FLAG_NO_DEFAULT_IPV4)) {
|
||||||
afi_header_vty_out(
|
vty_out(vty,
|
||||||
vty, afi, safi, write,
|
|
||||||
" no neighbor %s activate\n",
|
" no neighbor %s activate\n",
|
||||||
addr);
|
addr);
|
||||||
}
|
}
|
||||||
@ -6686,15 +6662,12 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
|||||||
/* addpath TX knobs */
|
/* addpath TX knobs */
|
||||||
if (peergroup_af_flag_check(peer, afi, safi,
|
if (peergroup_af_flag_check(peer, afi, safi,
|
||||||
PEER_FLAG_ADDPATH_TX_ALL_PATHS)) {
|
PEER_FLAG_ADDPATH_TX_ALL_PATHS)) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s addpath-tx-all-paths\n", addr);
|
||||||
" neighbor %s addpath-tx-all-paths\n",
|
|
||||||
addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (peergroup_af_flag_check(peer, afi, safi,
|
if (peergroup_af_flag_check(peer, afi, safi,
|
||||||
PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
|
PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s addpath-tx-bestpath-per-AS\n",
|
||||||
" neighbor %s addpath-tx-bestpath-per-AS\n",
|
|
||||||
addr);
|
addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6702,9 +6675,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
|||||||
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM)
|
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM)
|
||||||
|| peergroup_af_flag_check(peer, afi, safi,
|
|| peergroup_af_flag_check(peer, afi, safi,
|
||||||
PEER_FLAG_ORF_PREFIX_RM)) {
|
PEER_FLAG_ORF_PREFIX_RM)) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s capability orf prefix-list", addr);
|
||||||
" neighbor %s capability orf prefix-list",
|
|
||||||
addr);
|
|
||||||
|
|
||||||
if (peergroup_af_flag_check(peer, afi, safi,
|
if (peergroup_af_flag_check(peer, afi, safi,
|
||||||
PEER_FLAG_ORF_PREFIX_SM)
|
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. */
|
/* Route reflector client. */
|
||||||
if (peergroup_af_flag_check(peer, afi, safi,
|
if (peergroup_af_flag_check(peer, afi, safi,
|
||||||
PEER_FLAG_REFLECTOR_CLIENT)) {
|
PEER_FLAG_REFLECTOR_CLIENT)) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s route-reflector-client\n", addr);
|
||||||
" neighbor %s route-reflector-client\n",
|
|
||||||
addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* next-hop-self force */
|
/* next-hop-self force */
|
||||||
if (peergroup_af_flag_check(peer, afi, safi,
|
if (peergroup_af_flag_check(peer, afi, safi,
|
||||||
PEER_FLAG_FORCE_NEXTHOP_SELF)) {
|
PEER_FLAG_FORCE_NEXTHOP_SELF)) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s next-hop-self force\n", addr);
|
||||||
" neighbor %s next-hop-self force\n", addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* next-hop-self */
|
/* next-hop-self */
|
||||||
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)) {
|
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s next-hop-self\n", addr);
|
||||||
" neighbor %s next-hop-self\n", addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remove-private-AS */
|
/* remove-private-AS */
|
||||||
if (peergroup_af_flag_check(peer, afi, safi,
|
if (peergroup_af_flag_check(peer, afi, safi,
|
||||||
PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) {
|
PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) {
|
||||||
afi_header_vty_out(
|
vty_out(vty, " neighbor %s remove-private-AS all replace-AS\n",
|
||||||
vty, afi, safi, write,
|
|
||||||
" neighbor %s remove-private-AS all replace-AS\n",
|
|
||||||
addr);
|
addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (peergroup_af_flag_check(peer, afi, safi,
|
else if (peergroup_af_flag_check(peer, afi, safi,
|
||||||
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) {
|
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) {
|
||||||
afi_header_vty_out(
|
vty_out(vty, " neighbor %s remove-private-AS replace-AS\n",
|
||||||
vty, afi, safi, write,
|
|
||||||
" 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);
|
addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (peergroup_af_flag_check(peer, afi, safi,
|
||||||
|
PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
|
||||||
|
vty_out(vty, " neighbor %s remove-private-AS all\n", addr);
|
||||||
|
}
|
||||||
|
|
||||||
else if (peergroup_af_flag_check(peer, afi, safi,
|
else if (peergroup_af_flag_check(peer, afi, safi,
|
||||||
PEER_FLAG_REMOVE_PRIVATE_AS)) {
|
PEER_FLAG_REMOVE_PRIVATE_AS)) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s remove-private-AS\n", addr);
|
||||||
" neighbor %s remove-private-AS\n", addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* as-override */
|
/* as-override */
|
||||||
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
|
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s as-override\n", addr);
|
||||||
" neighbor %s as-override\n", addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send-community print. */
|
/* send-community print. */
|
||||||
@ -6784,27 +6744,21 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
|||||||
&& peergroup_af_flag_check(
|
&& peergroup_af_flag_check(
|
||||||
peer, afi, safi,
|
peer, afi, safi,
|
||||||
PEER_FLAG_SEND_LARGE_COMMUNITY)) {
|
PEER_FLAG_SEND_LARGE_COMMUNITY)) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s send-community all\n",
|
||||||
" neighbor %s send-community all\n",
|
|
||||||
addr);
|
addr);
|
||||||
} else if (peergroup_af_flag_check(
|
} else if (peergroup_af_flag_check(
|
||||||
peer, afi, safi,
|
peer, afi, safi,
|
||||||
PEER_FLAG_SEND_LARGE_COMMUNITY)) {
|
PEER_FLAG_SEND_LARGE_COMMUNITY)) {
|
||||||
afi_header_vty_out(
|
vty_out(vty, " neighbor %s send-community large\n",
|
||||||
vty, afi, safi, write,
|
addr);
|
||||||
" neighbor %s send-community large\n", addr);
|
|
||||||
} else if (peergroup_af_flag_check(
|
} else if (peergroup_af_flag_check(
|
||||||
peer, afi, safi,
|
peer, afi, safi,
|
||||||
PEER_FLAG_SEND_EXT_COMMUNITY)) {
|
PEER_FLAG_SEND_EXT_COMMUNITY)) {
|
||||||
afi_header_vty_out(
|
vty_out(vty, " neighbor %s send-community extended\n",
|
||||||
vty, afi, safi, write,
|
|
||||||
" neighbor %s send-community extended\n",
|
|
||||||
addr);
|
addr);
|
||||||
} else if (peergroup_af_flag_check(peer, afi, safi,
|
} else if (peergroup_af_flag_check(peer, afi, safi,
|
||||||
PEER_FLAG_SEND_COMMUNITY)) {
|
PEER_FLAG_SEND_COMMUNITY)) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s send-community\n", addr);
|
||||||
" neighbor %s send-community\n",
|
|
||||||
addr);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!peer_af_flag_check(peer, afi, safi,
|
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 || peer_af_flag_check(
|
||||||
g_peer, afi, safi,
|
g_peer, afi, safi,
|
||||||
PEER_FLAG_SEND_LARGE_COMMUNITY))) {
|
PEER_FLAG_SEND_LARGE_COMMUNITY))) {
|
||||||
afi_header_vty_out(
|
vty_out(vty, " no neighbor %s send-community all\n",
|
||||||
vty, afi, safi, write,
|
addr);
|
||||||
" no neighbor %s send-community all\n", addr);
|
|
||||||
} else {
|
} else {
|
||||||
if (!peer_af_flag_check(peer, afi, safi,
|
if (!peer_af_flag_check(peer, afi, safi,
|
||||||
PEER_FLAG_SEND_LARGE_COMMUNITY)
|
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(
|
|| peer_af_flag_check(
|
||||||
g_peer, afi, safi,
|
g_peer, afi, safi,
|
||||||
PEER_FLAG_SEND_LARGE_COMMUNITY))) {
|
PEER_FLAG_SEND_LARGE_COMMUNITY))) {
|
||||||
afi_header_vty_out(
|
vty_out(vty,
|
||||||
vty, afi, safi, write,
|
|
||||||
" no neighbor %s send-community large\n",
|
" no neighbor %s send-community large\n",
|
||||||
addr);
|
addr);
|
||||||
}
|
}
|
||||||
@ -6843,8 +6795,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
|||||||
|| peer_af_flag_check(
|
|| peer_af_flag_check(
|
||||||
g_peer, afi, safi,
|
g_peer, afi, safi,
|
||||||
PEER_FLAG_SEND_EXT_COMMUNITY))) {
|
PEER_FLAG_SEND_EXT_COMMUNITY))) {
|
||||||
afi_header_vty_out(
|
vty_out(vty,
|
||||||
vty, afi, safi, write,
|
|
||||||
" no neighbor %s send-community extended\n",
|
" no neighbor %s send-community extended\n",
|
||||||
addr);
|
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 || peer_af_flag_check(
|
||||||
g_peer, afi, safi,
|
g_peer, afi, safi,
|
||||||
PEER_FLAG_SEND_COMMUNITY))) {
|
PEER_FLAG_SEND_COMMUNITY))) {
|
||||||
afi_header_vty_out(
|
vty_out(vty,
|
||||||
vty, afi, safi, write,
|
|
||||||
" no neighbor %s send-community\n",
|
" no neighbor %s send-community\n",
|
||||||
addr);
|
addr);
|
||||||
}
|
}
|
||||||
@ -6873,8 +6823,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
|||||||
|| (peer->default_rmap[afi][safi].name
|
|| (peer->default_rmap[afi][safi].name
|
||||||
&& strcmp(peer->default_rmap[afi][safi].name,
|
&& strcmp(peer->default_rmap[afi][safi].name,
|
||||||
g_peer->default_rmap[afi][safi].name))))) {
|
g_peer->default_rmap[afi][safi].name))))) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s default-originate", addr);
|
||||||
" neighbor %s default-originate", addr);
|
|
||||||
if (peer->default_rmap[afi][safi].name)
|
if (peer->default_rmap[afi][safi].name)
|
||||||
vty_out(vty, " route-map %s",
|
vty_out(vty, " route-map %s",
|
||||||
peer->default_rmap[afi][safi].name);
|
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. */
|
/* Soft reconfiguration inbound. */
|
||||||
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_SOFT_RECONFIG)) {
|
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_SOFT_RECONFIG)) {
|
||||||
afi_header_vty_out(
|
vty_out(vty, " neighbor %s soft-reconfiguration inbound\n",
|
||||||
vty, afi, safi, write,
|
addr);
|
||||||
" neighbor %s soft-reconfiguration inbound\n", addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* maximum-prefix. */
|
/* maximum-prefix. */
|
||||||
@ -6898,9 +6846,8 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
|||||||
PEER_FLAG_MAX_PREFIX_WARNING)
|
PEER_FLAG_MAX_PREFIX_WARNING)
|
||||||
!= CHECK_FLAG(peer->af_flags[afi][safi],
|
!= CHECK_FLAG(peer->af_flags[afi][safi],
|
||||||
PEER_FLAG_MAX_PREFIX_WARNING)) {
|
PEER_FLAG_MAX_PREFIX_WARNING)) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s maximum-prefix %lu", addr,
|
||||||
" neighbor %s maximum-prefix %lu",
|
peer->pmax[afi][safi]);
|
||||||
addr, peer->pmax[afi][safi]);
|
|
||||||
if (peer->pmax_threshold[afi][safi]
|
if (peer->pmax_threshold[afi][safi]
|
||||||
!= MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
|
!= MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
|
||||||
vty_out(vty, " %u",
|
vty_out(vty, " %u",
|
||||||
@ -6917,16 +6864,13 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
|||||||
/* Route server client. */
|
/* Route server client. */
|
||||||
if (peergroup_af_flag_check(peer, afi, safi,
|
if (peergroup_af_flag_check(peer, afi, safi,
|
||||||
PEER_FLAG_RSERVER_CLIENT)) {
|
PEER_FLAG_RSERVER_CLIENT)) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s route-server-client\n", addr);
|
||||||
" neighbor %s route-server-client\n", addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Nexthop-local unchanged. */
|
/* Nexthop-local unchanged. */
|
||||||
if (peergroup_af_flag_check(peer, afi, safi,
|
if (peergroup_af_flag_check(peer, afi, safi,
|
||||||
PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) {
|
PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s nexthop-local unchanged\n", addr);
|
||||||
" neighbor %s nexthop-local unchanged\n",
|
|
||||||
addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allowas-in <1-10> */
|
/* 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]
|
|| peer->allowas_in[afi][safi]
|
||||||
!= g_peer->allowas_in[afi][safi]) {
|
!= g_peer->allowas_in[afi][safi]) {
|
||||||
if (peer->allowas_in[afi][safi] == 3) {
|
if (peer->allowas_in[afi][safi] == 3) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s allowas-in\n",
|
||||||
" neighbor %s allowas-in\n",
|
|
||||||
addr);
|
addr);
|
||||||
} else {
|
} else {
|
||||||
afi_header_vty_out(
|
vty_out(vty, " neighbor %s allowas-in %d\n",
|
||||||
vty, afi, safi, write,
|
addr, peer->allowas_in[afi][safi]);
|
||||||
" 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)
|
if (!peer_group_active(peer)
|
||||||
|| !peer_af_flag_check(g_peer, afi, safi,
|
|| !peer_af_flag_check(g_peer, afi, safi,
|
||||||
PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
|
PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s allowas-in origin\n", addr);
|
||||||
" 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_af_flag_check(g_peer, afi, safi, PEER_FLAG_WEIGHT)
|
||||||
|| peer->weight[afi][safi] != g_peer->weight[afi][safi]) {
|
|| peer->weight[afi][safi] != g_peer->weight[afi][safi]) {
|
||||||
if (peer->weight[afi][safi]) {
|
if (peer->weight[afi][safi]) {
|
||||||
afi_header_vty_out(vty, afi, safi, write,
|
vty_out(vty, " neighbor %s weight %lu\n", addr,
|
||||||
" neighbor %s weight %lu\n",
|
|
||||||
addr,
|
|
||||||
peer->weight[afi][safi]);
|
peer->weight[afi][safi]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Filter. */
|
/* Filter. */
|
||||||
bgp_config_write_filter(vty, peer, afi, safi, write);
|
bgp_config_write_filter(vty, peer, afi, safi);
|
||||||
|
|
||||||
/* atribute-unchanged. */
|
/* atribute-unchanged. */
|
||||||
if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_PATH_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,
|
peergroup_af_flag_check(peer, afi, safi,
|
||||||
PEER_FLAG_MED_UNCHANGED)) {
|
PEER_FLAG_MED_UNCHANGED)) {
|
||||||
|
|
||||||
afi_header_vty_out(
|
vty_out(vty,
|
||||||
vty, afi, safi, write,
|
|
||||||
" neighbor %s attribute-unchanged%s%s%s\n",
|
" neighbor %s attribute-unchanged%s%s%s\n",
|
||||||
addr,
|
addr,
|
||||||
peer_af_flag_check(
|
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. */
|
/* Address family based peer configuration display. */
|
||||||
static int bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
|
static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||||
safi_t safi)
|
safi_t safi)
|
||||||
{
|
{
|
||||||
int write = 0;
|
|
||||||
struct peer *peer;
|
struct peer *peer;
|
||||||
struct peer_group *group;
|
struct peer_group *group;
|
||||||
struct listnode *node, *nnode;
|
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))
|
for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
|
||||||
bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi,
|
bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi);
|
||||||
&write);
|
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
|
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
|
||||||
/* Skip dynamic neighbors. */
|
/* 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 */
|
/* Do not display doppelganger peers */
|
||||||
if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
|
if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
|
||||||
bgp_config_write_peer_af(vty, bgp, peer, afi, safi,
|
bgp_config_write_peer_af(vty, bgp, peer, afi, safi);
|
||||||
&write);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bgp_config_write_maxpaths(vty, bgp, afi, safi, &write);
|
bgp_config_write_maxpaths(vty, bgp, afi, safi);
|
||||||
bgp_config_write_table_map(vty, bgp, afi, safi, &write);
|
bgp_config_write_table_map(vty, bgp, afi, safi);
|
||||||
|
|
||||||
if (safi == SAFI_EVPN)
|
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_endframe(vty, " exit-address-family\n");
|
||||||
vty_out(vty, " exit-address-family\n");
|
|
||||||
|
|
||||||
return write;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int bgp_config_write(struct vty *vty)
|
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",
|
vty_out(vty, "bgp route-map delay-timer %u\n",
|
||||||
bm->rmap_update_timer);
|
bm->rmap_update_timer);
|
||||||
|
|
||||||
/* BGP configuration. */
|
|
||||||
for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
|
|
||||||
if (write)
|
if (write)
|
||||||
vty_out(vty, "!\n");
|
vty_out(vty, "!\n");
|
||||||
|
|
||||||
|
/* BGP configuration. */
|
||||||
|
for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
|
||||||
/* Router bgp ASN */
|
/* Router bgp ASN */
|
||||||
vty_out(vty, "router bgp %u", bgp->as);
|
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");
|
vty_out(vty, " no auto-summary\n");
|
||||||
|
|
||||||
/* IPv4 unicast configuration. */
|
/* 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. */
|
/* IPv4 multicast configuration. */
|
||||||
write += bgp_config_write_family(vty, bgp, AFI_IP,
|
bgp_config_write_family(vty, bgp, AFI_IP, SAFI_MULTICAST);
|
||||||
SAFI_MULTICAST);
|
|
||||||
|
|
||||||
/* IPv4 labeled-unicast configuration. */
|
/* IPv4 labeled-unicast configuration. */
|
||||||
write += bgp_config_write_family(vty, bgp, AFI_IP,
|
bgp_config_write_family(vty, bgp, AFI_IP, SAFI_LABELED_UNICAST);
|
||||||
SAFI_LABELED_UNICAST);
|
|
||||||
|
|
||||||
/* IPv4 VPN configuration. */
|
/* IPv4 VPN configuration. */
|
||||||
write += bgp_config_write_family(vty, bgp, AFI_IP,
|
bgp_config_write_family(vty, bgp, AFI_IP, SAFI_MPLS_VPN);
|
||||||
SAFI_MPLS_VPN);
|
|
||||||
|
|
||||||
/* ENCAPv4 configuration. */
|
/* 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. */
|
/* IPv6 unicast configuration. */
|
||||||
write += bgp_config_write_family(vty, bgp, AFI_IP6,
|
bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_UNICAST);
|
||||||
SAFI_UNICAST);
|
|
||||||
|
|
||||||
/* IPv6 multicast configuration. */
|
/* IPv6 multicast configuration. */
|
||||||
write += bgp_config_write_family(vty, bgp, AFI_IP6,
|
bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_MULTICAST);
|
||||||
SAFI_MULTICAST);
|
|
||||||
|
|
||||||
/* IPv6 labeled-unicast configuration. */
|
/* IPv6 labeled-unicast configuration. */
|
||||||
write += bgp_config_write_family(vty, bgp, AFI_IP6,
|
bgp_config_write_family(vty, bgp, AFI_IP6,
|
||||||
SAFI_LABELED_UNICAST);
|
SAFI_LABELED_UNICAST);
|
||||||
|
|
||||||
/* IPv6 VPN configuration. */
|
/* IPv6 VPN configuration. */
|
||||||
write += bgp_config_write_family(vty, bgp, AFI_IP6,
|
bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
|
||||||
SAFI_MPLS_VPN);
|
|
||||||
|
|
||||||
/* ENCAPv6 configuration. */
|
/* 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. */
|
/* 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
|
#if ENABLE_BGP_VNC
|
||||||
write += bgp_rfapi_cfg_write(vty, bgp);
|
bgp_rfapi_cfg_write(vty, bgp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
write++;
|
vty_out(vty, "!\n");
|
||||||
}
|
}
|
||||||
return write;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bgp_master_init(struct thread_master *master)
|
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 char *peer_uptime(time_t, char *, size_t, u_char, json_object *);
|
||||||
|
|
||||||
extern int bgp_config_write(struct vty *);
|
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);
|
extern void bgp_master_init(struct thread_master *master);
|
||||||
|
|
||||||
|
@ -1837,6 +1837,7 @@ AC_CONFIG_FILES([Makefile
|
|||||||
doc/watchfrr.8
|
doc/watchfrr.8
|
||||||
doc/zebra.8
|
doc/zebra.8
|
||||||
doc/frr.1
|
doc/frr.1
|
||||||
|
doc/frr-args.8
|
||||||
pkgsrc/bgpd.sh pkgsrc/ospf6d.sh pkgsrc/ospfd.sh
|
pkgsrc/bgpd.sh pkgsrc/ospf6d.sh pkgsrc/ospfd.sh
|
||||||
pkgsrc/ripd.sh pkgsrc/ripngd.sh pkgsrc/zebra.sh
|
pkgsrc/ripd.sh pkgsrc/ripngd.sh pkgsrc/zebra.sh
|
||||||
pkgsrc/eigrpd.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/zebra.8
|
||||||
usr/share/man/man8/isisd.8
|
usr/share/man/man8/isisd.8
|
||||||
usr/share/man/man8/watchfrr.8
|
usr/share/man/man8/watchfrr.8
|
||||||
|
usr/share/man/man8/frr-args.8
|
||||||
usr/share/snmp/mibs/
|
usr/share/snmp/mibs/
|
||||||
tools/etc/* etc/
|
tools/etc/* etc/
|
||||||
tools/*.service lib/systemd/system
|
tools/*.service lib/systemd/system
|
||||||
|
@ -79,7 +79,7 @@ frr_TEXINFOS = appendix.texi basic.texi bgpd.texi isisd.texi filter.texi \
|
|||||||
.dia.png:
|
.dia.png:
|
||||||
$(DIATOPNG) "$@" $<
|
$(DIATOPNG) "$@" $<
|
||||||
|
|
||||||
man_MANS = frr.1
|
man_MANS = frr.1 frr-args.8
|
||||||
|
|
||||||
if PIMD
|
if PIMD
|
||||||
man_MANS += pimd.8
|
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;
|
struct listnode *node;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) {
|
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)
|
if ((IF_DEF_PARAMS(ei->ifp)->auth_type)
|
||||||
== EIGRP_AUTH_TYPE_MD5) {
|
== 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*/
|
/*Separate this EIGRP interface configuration from the others*/
|
||||||
vty_out(vty, "!\n");
|
vty_endframe(vty, "!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -140,7 +140,7 @@ static int eigrp_write_interface(struct vty *vty)
|
|||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, 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)
|
if (ifp->desc)
|
||||||
vty_out(vty, " description %s\n", 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",
|
vty_out(vty, " ip hold-time eigrp %u\n",
|
||||||
IF_DEF_PARAMS(ifp)->v_wait);
|
IF_DEF_PARAMS(ifp)->v_wait);
|
||||||
|
|
||||||
vty_out(vty, "!\n");
|
vty_endframe(vty, "!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -948,7 +948,7 @@ int isis_interface_config_write(struct vty *vty)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* IF name */
|
/* IF name */
|
||||||
vty_out(vty, "interface %s\n", ifp->name);
|
vty_frame(vty, "interface %s\n", ifp->name);
|
||||||
write++;
|
write++;
|
||||||
/* IF desc */
|
/* IF desc */
|
||||||
if (ifp->desc) {
|
if (ifp->desc) {
|
||||||
@ -1145,7 +1145,7 @@ int isis_interface_config_write(struct vty *vty)
|
|||||||
}
|
}
|
||||||
write += circuit_write_mt_settings(circuit, vty);
|
write += circuit_write_mt_settings(circuit, vty);
|
||||||
}
|
}
|
||||||
vty_out(vty, "!\n");
|
vty_endframe(vty, "!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return write;
|
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[] = {
|
static const struct option lo_cfg_pid_dry[] = {
|
||||||
{"pid_file", required_argument, NULL, 'i'},
|
{"pid_file", required_argument, NULL, 'i'},
|
||||||
{"config_file", required_argument, NULL, 'f'},
|
{"config_file", required_argument, NULL, 'f'},
|
||||||
|
{"pathspace", required_argument, NULL, 'N'},
|
||||||
{"dryrun", no_argument, NULL, 'C'},
|
{"dryrun", no_argument, NULL, 'C'},
|
||||||
{"terminal", no_argument, NULL, 't'},
|
{"terminal", no_argument, NULL, 't'},
|
||||||
{NULL}};
|
{NULL}};
|
||||||
static const struct optspec os_cfg_pid_dry = {
|
static const struct optspec os_cfg_pid_dry = {
|
||||||
"f:i:Ct",
|
"f:i:CtN:",
|
||||||
" -f, --config_file Set configuration file name\n"
|
" -f, --config_file Set configuration file name\n"
|
||||||
" -i, --pid_file Set process identifier 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"
|
" -C, --dryrun Check configuration for validity and exit\n"
|
||||||
" -t, --terminal Open terminal session on stdio\n"
|
" -t, --terminal Open terminal session on stdio\n"
|
||||||
" -d -t Daemonize after terminal session ends\n",
|
" -d -t Daemonize after terminal session ends\n",
|
||||||
@ -351,6 +353,23 @@ static int frr_opt(int opt)
|
|||||||
return 1;
|
return 1;
|
||||||
di->config_file = optarg;
|
di->config_file = optarg;
|
||||||
break;
|
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':
|
case 'C':
|
||||||
if (di->flags & FRR_NO_CFG_PID_DRY)
|
if (di->flags & FRR_NO_CFG_PID_DRY)
|
||||||
return 1;
|
return 1;
|
||||||
@ -500,14 +519,25 @@ struct thread_master *frr_init(void)
|
|||||||
struct option_chain *oc;
|
struct option_chain *oc;
|
||||||
struct frrmod_runtime *module;
|
struct frrmod_runtime *module;
|
||||||
char moderr[256];
|
char moderr[256];
|
||||||
|
char p_instance[16] = "", p_pathspace[256] = "";
|
||||||
const char *dir;
|
const char *dir;
|
||||||
dir = di->module_path ? di->module_path : frr_moduledir;
|
dir = di->module_path ? di->module_path : frr_moduledir;
|
||||||
|
|
||||||
srandom(time(NULL));
|
srandom(time(NULL));
|
||||||
|
|
||||||
if (di->instance)
|
if (di->instance) {
|
||||||
snprintf(frr_protonameinst, sizeof(frr_protonameinst), "%s[%u]",
|
snprintf(frr_protonameinst, sizeof(frr_protonameinst), "%s[%u]",
|
||||||
di->logname, di->instance);
|
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);
|
zprivs_preinit(di->privs);
|
||||||
|
|
||||||
@ -695,14 +725,6 @@ void frr_config_fork(void)
|
|||||||
{
|
{
|
||||||
hook_call(frr_late_init, master);
|
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);
|
vty_read_config(di->config_file, config_default);
|
||||||
|
|
||||||
/* Don't start execution if we are in dry-run mode */
|
/* Don't start execution if we are in dry-run mode */
|
||||||
@ -723,7 +745,13 @@ void frr_vty_serv(void)
|
|||||||
* (not currently set anywhere) */
|
* (not currently set anywhere) */
|
||||||
if (!di->vty_path) {
|
if (!di->vty_path) {
|
||||||
const char *dir;
|
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)
|
if (di->instance)
|
||||||
snprintf(vtypath_default, sizeof(vtypath_default),
|
snprintf(vtypath_default, sizeof(vtypath_default),
|
||||||
|
@ -54,6 +54,7 @@ struct frr_daemon_info {
|
|||||||
const char *pid_file;
|
const char *pid_file;
|
||||||
const char *vty_path;
|
const char *vty_path;
|
||||||
const char *module_path;
|
const char *module_path;
|
||||||
|
const char *pathspace;
|
||||||
|
|
||||||
const char *proghelp;
|
const char *proghelp;
|
||||||
void (*printhelp)(FILE *target);
|
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;
|
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. */
|
/* VTY standard output function. */
|
||||||
int vty_out(struct vty *vty, const char *format, ...)
|
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 buf[1024];
|
||||||
char *p = NULL;
|
char *p = NULL;
|
||||||
|
|
||||||
|
if (vty->frame_pos) {
|
||||||
|
vty->frame_pos = 0;
|
||||||
|
vty_out(vty, "%s", vty->frame);
|
||||||
|
}
|
||||||
|
|
||||||
if (vty_shell(vty)) {
|
if (vty_shell(vty)) {
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
vprintf(format, args);
|
vprintf(format, args);
|
||||||
|
15
lib/vty.h
15
lib/vty.h
@ -125,6 +125,12 @@ struct vty {
|
|||||||
|
|
||||||
/* What address is this vty comming from. */
|
/* What address is this vty comming from. */
|
||||||
char address[SU_ADDRSTRLEN];
|
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)
|
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 void vty_reset(void);
|
||||||
extern struct vty *vty_new(void);
|
extern struct vty *vty_new(void);
|
||||||
extern struct vty *vty_stdio(void (*atclose)(int isexit));
|
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 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_read_config(const char *, char *);
|
||||||
extern void vty_time_print(struct vty *, int);
|
extern void vty_time_print(struct vty *, int);
|
||||||
extern void vty_serv_sock(const char *, unsigned short, const char *);
|
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;
|
int i;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, 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)
|
if (ifp->desc)
|
||||||
vty_out (vty, " description %s\n", 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;
|
return 0;
|
||||||
|
@ -1755,7 +1755,7 @@ static int config_write_ospf6_interface(struct vty *vty)
|
|||||||
if (oi == NULL)
|
if (oi == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
vty_out(vty, "interface %s\n", oi->interface->name);
|
vty_frame(vty, "interface %s\n", oi->interface->name);
|
||||||
|
|
||||||
if (ifp->desc)
|
if (ifp->desc)
|
||||||
vty_out(vty, " description %s\n", 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);
|
ospf6_bfd_write_config(vty, oi);
|
||||||
|
|
||||||
vty_out(vty, "!\n");
|
vty_endframe(vty, "!\n");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -8156,8 +8156,8 @@ static int config_write_interface(struct vty *vty)
|
|||||||
if (ifp->ifindex == IFINDEX_DELETED)
|
if (ifp->ifindex == IFINDEX_DELETED)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
vty_out(vty, "!\n");
|
vty_frame(vty, "!\n");
|
||||||
vty_out(vty, "interface %s\n", ifp->name);
|
vty_frame(vty, "interface %s\n", ifp->name);
|
||||||
if (ifp->desc)
|
if (ifp->desc)
|
||||||
vty_out(vty, " description %s\n", ifp->desc);
|
vty_out(vty, " description %s\n", ifp->desc);
|
||||||
|
|
||||||
@ -8371,6 +8371,8 @@ static int config_write_interface(struct vty *vty)
|
|||||||
} while (rn);
|
} while (rn);
|
||||||
|
|
||||||
ospf_opaque_config_write_if(vty, ifp);
|
ospf_opaque_config_write_if(vty, ifp);
|
||||||
|
|
||||||
|
vty_endframe(vty, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return write;
|
return write;
|
||||||
|
@ -255,7 +255,7 @@ int pim_interface_config_write(struct vty *vty)
|
|||||||
|
|
||||||
/* IF name */
|
/* IF name */
|
||||||
if (vrf->vrf_id == VRF_DEFAULT)
|
if (vrf->vrf_id == VRF_DEFAULT)
|
||||||
vty_out(vty, "interface %s\n", ifp->name);
|
vty_frame(vty, "interface %s\n", ifp->name);
|
||||||
else
|
else
|
||||||
vty_out(vty, "interface %s vrf %s\n", ifp->name,
|
vty_out(vty, "interface %s vrf %s\n", ifp->name,
|
||||||
vrf->name);
|
vrf->name);
|
||||||
@ -363,7 +363,7 @@ int pim_interface_config_write(struct vty *vty)
|
|||||||
pim_static_write_mroute(pim, vty, ifp);
|
pim_static_write_mroute(pim, vty, ifp);
|
||||||
pim_bfd_write_config(vty, ifp);
|
pim_bfd_write_config(vty, ifp);
|
||||||
}
|
}
|
||||||
vty_out(vty, "!\n");
|
vty_endframe(vty, "!\n");
|
||||||
++writes;
|
++writes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1751,7 +1751,7 @@ static int rip_interface_config_write(struct vty *vty)
|
|||||||
&& (!ri->auth_str) && (!ri->key_chain))
|
&& (!ri->auth_str) && (!ri->key_chain))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
vty_out(vty, "interface %s\n", ifp->name);
|
vty_frame(vty, "interface %s\n", ifp->name);
|
||||||
|
|
||||||
if (ifp->desc)
|
if (ifp->desc)
|
||||||
vty_out(vty, " description %s\n", 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",
|
vty_out(vty, " ip rip authentication key-chain %s\n",
|
||||||
ri->key_chain);
|
ri->key_chain);
|
||||||
|
|
||||||
vty_out(vty, "!\n");
|
vty_endframe(vty, "!\n");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1084,7 +1084,7 @@ static int interface_config_write(struct vty *vty)
|
|||||||
&& (ri->split_horizon == ri->split_horizon_default))
|
&& (ri->split_horizon == ri->split_horizon_default))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
vty_out(vty, "interface %s\n", ifp->name);
|
vty_frame(vty, "interface %s\n", ifp->name);
|
||||||
if (ifp->desc)
|
if (ifp->desc)
|
||||||
vty_out(vty, " description %s\n", 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++;
|
write++;
|
||||||
}
|
}
|
||||||
|
@ -2295,12 +2295,12 @@ int vtysh_write_config_integrated(void)
|
|||||||
|
|
||||||
fprintf(stdout, "Building Configuration...\n");
|
fprintf(stdout, "Building Configuration...\n");
|
||||||
|
|
||||||
backup_config_file(quagga_config);
|
backup_config_file(frr_config);
|
||||||
fp = fopen(quagga_config, "w");
|
fp = fopen(frr_config, "w");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
fprintf(stdout,
|
fprintf(stdout,
|
||||||
"%% Error: failed to open configuration file %s: %s\n",
|
"%% Error: failed to open configuration file %s: %s\n",
|
||||||
quagga_config, safe_strerror(errno));
|
frr_config, safe_strerror(errno));
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
}
|
}
|
||||||
fd = fileno(fp);
|
fd = fileno(fp);
|
||||||
@ -2313,7 +2313,7 @@ int vtysh_write_config_integrated(void)
|
|||||||
|
|
||||||
if (fchmod(fd, CONFIGFILE_MASK) != 0) {
|
if (fchmod(fd, CONFIGFILE_MASK) != 0) {
|
||||||
printf("%% Warning: can't chmod configuration file %s: %s\n",
|
printf("%% Warning: can't chmod configuration file %s: %s\n",
|
||||||
quagga_config, safe_strerror(errno));
|
frr_config, safe_strerror(errno));
|
||||||
err++;
|
err++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2345,18 +2345,18 @@ int vtysh_write_config_integrated(void)
|
|||||||
if ((uid != (uid_t)-1 || gid != (gid_t)-1)
|
if ((uid != (uid_t)-1 || gid != (gid_t)-1)
|
||||||
&& fchown(fd, uid, gid)) {
|
&& fchown(fd, uid, gid)) {
|
||||||
printf("%% Warning: can't chown configuration file %s: %s\n",
|
printf("%% Warning: can't chown configuration file %s: %s\n",
|
||||||
quagga_config, safe_strerror(errno));
|
frr_config, safe_strerror(errno));
|
||||||
err++;
|
err++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("%% Warning: stat() failed on %s: %s\n", quagga_config,
|
printf("%% Warning: stat() failed on %s: %s\n", frr_config,
|
||||||
safe_strerror(errno));
|
safe_strerror(errno));
|
||||||
err++;
|
err++;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
printf("Integrated configuration saved to %s\n", quagga_config);
|
printf("Integrated configuration saved to %s\n", frr_config);
|
||||||
if (err)
|
if (err)
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
|
|
||||||
@ -2370,7 +2370,7 @@ static bool want_config_integrated(void)
|
|||||||
|
|
||||||
switch (vtysh_write_integrated) {
|
switch (vtysh_write_integrated) {
|
||||||
case WRITE_INTEGRATED_UNSPECIFIED:
|
case WRITE_INTEGRATED_UNSPECIFIED:
|
||||||
if (stat(quagga_config, &s) && errno == ENOENT)
|
if (stat(frr_config, &s) && errno == ENOENT)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
case WRITE_INTEGRATED_NO:
|
case WRITE_INTEGRATED_NO:
|
||||||
@ -2712,7 +2712,7 @@ static int vtysh_connect(struct vtysh_client *vclient)
|
|||||||
|
|
||||||
if (!vclient->path[0])
|
if (!vclient->path[0])
|
||||||
snprintf(vclient->path, sizeof(vclient->path), "%s/%s.vty",
|
snprintf(vclient->path, sizeof(vclient->path), "%s/%s.vty",
|
||||||
vty_sock_path, vclient->name);
|
vtydir, vclient->name);
|
||||||
path = vclient->path;
|
path = vclient->path;
|
||||||
|
|
||||||
/* Stat socket to see if we have permission to access it. */
|
/* 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;
|
return;
|
||||||
|
|
||||||
/* ls vty_sock_dir and look for all files ending in .vty */
|
/* ls vty_sock_dir and look for all files ending in .vty */
|
||||||
dir = opendir(vty_sock_path);
|
dir = opendir(vtydir);
|
||||||
if (dir) {
|
if (dir) {
|
||||||
while ((file = readdir(dir)) != NULL) {
|
while ((file = readdir(dir)) != NULL) {
|
||||||
if (begins_with(file->d_name, "ospfd-")
|
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) {
|
if (n == MAXIMUM_INSTANCES) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Parsing %s, client limit(%d) reached!\n",
|
"Parsing %s, client limit(%d) reached!\n",
|
||||||
vty_sock_path, n);
|
vtydir, n);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
client = (struct vtysh_client *)malloc(
|
client = (struct vtysh_client *)malloc(
|
||||||
@ -2823,7 +2823,7 @@ static void vtysh_update_all_insances(struct vtysh_client *head_client)
|
|||||||
client->name = "ospfd";
|
client->name = "ospfd";
|
||||||
client->flag = VTYSH_OSPFD;
|
client->flag = VTYSH_OSPFD;
|
||||||
snprintf(client->path, sizeof(client->path),
|
snprintf(client->path, sizeof(client->path),
|
||||||
"%s/%s", vty_sock_path, file->d_name);
|
"%s/%s", vtydir, file->d_name);
|
||||||
client->next = NULL;
|
client->next = NULL;
|
||||||
vtysh_client_sorted_insert(head_client, client);
|
vtysh_client_sorted_insert(head_client, client);
|
||||||
n++;
|
n++;
|
||||||
|
@ -49,10 +49,6 @@ DECLARE_MGROUP(MVTYSH)
|
|||||||
#define VTYSH_NS VTYSH_ZEBRA
|
#define VTYSH_NS VTYSH_ZEBRA
|
||||||
#define VTYSH_VRF VTYSH_ZEBRA|VTYSH_PIMD
|
#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 {
|
enum vtysh_write_integrated {
|
||||||
WRITE_INTEGRATED_UNSPECIFIED,
|
WRITE_INTEGRATED_UNSPECIFIED,
|
||||||
WRITE_INTEGRATED_NO,
|
WRITE_INTEGRATED_NO,
|
||||||
@ -61,7 +57,8 @@ enum vtysh_write_integrated {
|
|||||||
|
|
||||||
extern enum vtysh_write_integrated 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_vty(void);
|
||||||
void vtysh_init_cmd(void);
|
void vtysh_init_cmd(void);
|
||||||
@ -93,11 +90,12 @@ void vtysh_config_init(void);
|
|||||||
|
|
||||||
void vtysh_pager_init(void);
|
void vtysh_pager_init(void);
|
||||||
|
|
||||||
|
void suid_on(void);
|
||||||
|
void suid_off(void);
|
||||||
|
|
||||||
/* Child process execution flag. */
|
/* Child process execution flag. */
|
||||||
extern int execute_flag;
|
extern int execute_flag;
|
||||||
|
|
||||||
extern struct vty *vty;
|
extern struct vty *vty;
|
||||||
|
|
||||||
extern const char *vty_sock_path;
|
|
||||||
|
|
||||||
#endif /* VTYSH_H */
|
#endif /* VTYSH_H */
|
||||||
|
@ -44,18 +44,22 @@
|
|||||||
/* VTY shell program name. */
|
/* VTY shell program name. */
|
||||||
char *progname;
|
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. */
|
/* Configuration file name and directory. */
|
||||||
static char vtysh_config_always[MAXPATHLEN] = SYSCONFDIR VTYSH_DEFAULT_CONFIG;
|
static char vtysh_config[MAXPATHLEN];
|
||||||
static char quagga_config_default[MAXPATHLEN] = SYSCONFDIR FRR_DEFAULT_CONFIG;
|
char frr_config[MAXPATHLEN];
|
||||||
char *quagga_config = quagga_config_default;
|
char vtydir[MAXPATHLEN];
|
||||||
char history_file[MAXPATHLEN];
|
static char history_file[MAXPATHLEN];
|
||||||
|
|
||||||
/* Flag for indicate executing child command. */
|
/* Flag for indicate executing child command. */
|
||||||
int execute_flag = 0;
|
int execute_flag = 0;
|
||||||
|
|
||||||
/* VTY Socket prefix */
|
|
||||||
const char *vty_sock_path = NULL;
|
|
||||||
|
|
||||||
/* For sigsetjmp() & siglongjmp(). */
|
/* For sigsetjmp() & siglongjmp(). */
|
||||||
static sigjmp_buf jmpbuf;
|
static sigjmp_buf jmpbuf;
|
||||||
|
|
||||||
@ -145,6 +149,7 @@ static void usage(int status)
|
|||||||
"-m, --markfile Mark input file with context end\n"
|
"-m, --markfile Mark input file with context end\n"
|
||||||
" --vty_socket Override vty socket path\n"
|
" --vty_socket Override vty socket path\n"
|
||||||
" --config_dir Override config directory 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"
|
"-w, --writeconfig Write integrated config (frr.conf) and exit\n"
|
||||||
"-h, --help Display this help and exit\n\n"
|
"-h, --help Display this help and exit\n\n"
|
||||||
"Note that multiple commands may be executed from the command\n"
|
"Note that multiple commands may be executed from the command\n"
|
||||||
@ -174,6 +179,7 @@ struct option longopts[] = {
|
|||||||
{"noerror", no_argument, NULL, 'n'},
|
{"noerror", no_argument, NULL, 'n'},
|
||||||
{"mark", no_argument, NULL, 'm'},
|
{"mark", no_argument, NULL, 'm'},
|
||||||
{"writeconfig", no_argument, NULL, 'w'},
|
{"writeconfig", no_argument, NULL, 'w'},
|
||||||
|
{"pathspace", no_argument, NULL, 'N'},
|
||||||
{0}};
|
{0}};
|
||||||
|
|
||||||
/* Read a string, and return a pointer to it. Returns NULL on EOF. */
|
/* 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);
|
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. */
|
/* VTY shell main routine. */
|
||||||
int main(int argc, char **argv, char **env)
|
int main(int argc, char **argv, char **env)
|
||||||
{
|
{
|
||||||
@ -258,7 +288,6 @@ int main(int argc, char **argv, char **env)
|
|||||||
int boot_flag = 0;
|
int boot_flag = 0;
|
||||||
const char *daemon_name = NULL;
|
const char *daemon_name = NULL;
|
||||||
const char *inputfile = NULL;
|
const char *inputfile = NULL;
|
||||||
const char *vtysh_configfile_name;
|
|
||||||
struct cmd_rec {
|
struct cmd_rec {
|
||||||
char *line;
|
char *line;
|
||||||
struct cmd_rec *next;
|
struct cmd_rec *next;
|
||||||
@ -270,16 +299,22 @@ int main(int argc, char **argv, char **env)
|
|||||||
int writeconfig = 0;
|
int writeconfig = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
char *homedir = NULL;
|
char *homedir = NULL;
|
||||||
|
int ditch_suid = 0;
|
||||||
|
char sysconfdir[MAXPATHLEN];
|
||||||
|
char pathspace[MAXPATHLEN] = "";
|
||||||
|
|
||||||
/* check for restricted functionality if vtysh is run setuid */
|
/* SUID: drop down to calling user & go back up when needed */
|
||||||
int restricted = (getuid() != geteuid()) || (getgid() != getegid());
|
elevuid = geteuid();
|
||||||
|
elevgid = getegid();
|
||||||
|
realuid = getuid();
|
||||||
|
realgid = getgid();
|
||||||
|
suid_off();
|
||||||
|
|
||||||
/* Preserve name of myself. */
|
/* Preserve name of myself. */
|
||||||
progname = ((p = strrchr(argv[0], '/')) ? ++p : argv[0]);
|
progname = ((p = strrchr(argv[0], '/')) ? ++p : argv[0]);
|
||||||
|
|
||||||
/* if logging open now */
|
strlcpy(sysconfdir, frr_sysconfdir, sizeof(sysconfdir));
|
||||||
if ((p = getenv("VTYSH_LOG")) != NULL)
|
strlcpy(vtydir, frr_vtydir, sizeof(vtydir));
|
||||||
logfile = fopen(p, "a");
|
|
||||||
|
|
||||||
/* Option handling. */
|
/* Option handling. */
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -307,63 +342,20 @@ int main(int argc, char **argv, char **env)
|
|||||||
tail = cr;
|
tail = cr;
|
||||||
} break;
|
} break;
|
||||||
case OPTION_VTYSOCK:
|
case OPTION_VTYSOCK:
|
||||||
vty_sock_path = optarg;
|
ditch_suid = 1; /* option disables SUID */
|
||||||
|
strlcpy(vtydir, optarg, sizeof(vtydir));
|
||||||
break;
|
break;
|
||||||
case OPTION_CONFDIR:
|
case OPTION_CONFDIR:
|
||||||
/*
|
ditch_suid = 1; /* option disables SUID */
|
||||||
* Skip option for Config Directory if setuid
|
strlcpy(sysconfdir, optarg, sizeof(sysconfdir));
|
||||||
*/
|
break;
|
||||||
if (restricted) {
|
case 'N':
|
||||||
|
if (strchr(optarg, '/') || strchr(optarg, '.')) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Overriding of Config Directory blocked for vtysh with setuid");
|
"slashes or dots are not permitted in the --pathspace option.\n");
|
||||||
return 1;
|
exit(1);
|
||||||
}
|
}
|
||||||
/*
|
snprintf(pathspace, sizeof(pathspace), "/%s", optarg);
|
||||||
* 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));
|
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
daemon_name = optarg;
|
daemon_name = optarg;
|
||||||
@ -395,8 +387,10 @@ int main(int argc, char **argv, char **env)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vty_sock_path)
|
if (ditch_suid) {
|
||||||
vty_sock_path = frr_vtydir;
|
elevuid = realuid;
|
||||||
|
elevgid = realgid;
|
||||||
|
}
|
||||||
|
|
||||||
if (markfile + writeconfig + dryrun + boot_flag > 1) {
|
if (markfile + writeconfig + dryrun + boot_flag > 1) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@ -410,6 +404,12 @@ int main(int argc, char **argv, char **env)
|
|||||||
"NOT SUPPORTED since its\nresults are inconsistent!\n");
|
"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. */
|
/* Initialize user input buffer. */
|
||||||
line_read = NULL;
|
line_read = NULL;
|
||||||
setlinebuf(stdout);
|
setlinebuf(stdout);
|
||||||
@ -425,8 +425,11 @@ int main(int argc, char **argv, char **env)
|
|||||||
|
|
||||||
vty_init_vtysh();
|
vty_init_vtysh();
|
||||||
|
|
||||||
/* Read vtysh configuration file before connecting to daemons. */
|
/* Read vtysh configuration file before connecting to daemons.
|
||||||
vtysh_read_config(vtysh_config_always);
|
* (file may not be readable to calling user in SUID mode) */
|
||||||
|
suid_on();
|
||||||
|
vtysh_read_config(vtysh_config);
|
||||||
|
suid_off();
|
||||||
|
|
||||||
if (markfile) {
|
if (markfile) {
|
||||||
if (!inputfile) {
|
if (!inputfile) {
|
||||||
@ -442,7 +445,7 @@ int main(int argc, char **argv, char **env)
|
|||||||
if (inputfile) {
|
if (inputfile) {
|
||||||
ret = vtysh_read_config(inputfile);
|
ret = vtysh_read_config(inputfile);
|
||||||
} else {
|
} else {
|
||||||
ret = vtysh_read_config(quagga_config_default);
|
ret = vtysh_read_config(frr_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit(ret);
|
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. */
|
/* Make sure we pass authentication before proceeding. */
|
||||||
vtysh_auth();
|
vtysh_auth();
|
||||||
|
|
||||||
@ -498,6 +504,9 @@ int main(int argc, char **argv, char **env)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* SUID: back down, don't need privs further on */
|
||||||
|
suid_off();
|
||||||
|
|
||||||
if (writeconfig) {
|
if (writeconfig) {
|
||||||
vtysh_execute("enable");
|
vtysh_execute("enable");
|
||||||
return vtysh_write_config_integrated();
|
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 eval mode. */
|
||||||
if (cmd) {
|
if (cmd) {
|
||||||
/* Enter into enable node. */
|
/* Enter into enable node. */
|
||||||
@ -592,13 +612,13 @@ int main(int argc, char **argv, char **env)
|
|||||||
|
|
||||||
/* Boot startup configuration file. */
|
/* Boot startup configuration file. */
|
||||||
if (boot_flag) {
|
if (boot_flag) {
|
||||||
vtysh_flock_config(quagga_config);
|
vtysh_flock_config(frr_config);
|
||||||
int ret = vtysh_read_config(quagga_config);
|
int ret = vtysh_read_config(frr_config);
|
||||||
vtysh_unflock_config();
|
vtysh_unflock_config();
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Configuration file[%s] processing failure: %d\n",
|
"Configuration file[%s] processing failure: %d\n",
|
||||||
quagga_config, ret);
|
frr_config, ret);
|
||||||
if (no_error)
|
if (no_error)
|
||||||
exit(0);
|
exit(0);
|
||||||
else
|
else
|
||||||
|
@ -2793,7 +2793,7 @@ static int if_config_write(struct vty *vty)
|
|||||||
vrf = vrf_lookup_by_id(ifp->vrf_id);
|
vrf = vrf_lookup_by_id(ifp->vrf_id);
|
||||||
|
|
||||||
if (ifp->vrf_id == VRF_DEFAULT)
|
if (ifp->vrf_id == VRF_DEFAULT)
|
||||||
vty_out(vty, "interface %s\n", ifp->name);
|
vty_frame(vty, "interface %s\n", ifp->name);
|
||||||
else
|
else
|
||||||
vty_out(vty, "interface %s vrf %s\n", ifp->name,
|
vty_out(vty, "interface %s vrf %s\n", ifp->name,
|
||||||
vrf->name);
|
vrf->name);
|
||||||
@ -2844,7 +2844,7 @@ static int if_config_write(struct vty *vty)
|
|||||||
|
|
||||||
link_params_config_write(vty, ifp);
|
link_params_config_write(vty, ifp);
|
||||||
|
|
||||||
vty_out(vty, "!\n");
|
vty_endframe(vty, "!\n");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user