Merge pull request #1056 from opensourcerouting/oldbits-0

"pathspace" options, vtysh-suid-cleanups, "vty_frame()"
This commit is contained in:
Donald Sharp 2017-08-29 17:48:36 -04:00 committed by GitHub
commit 32592ffb4f
30 changed files with 1538 additions and 1381 deletions

View File

@ -1321,7 +1321,7 @@ interface_config_write (struct vty *vty)
int write = 0;
for (ALL_LIST_ELEMENTS_RO (vrf_iflist(VRF_DEFAULT), node, ifp)) {
vty_out (vty, "interface %s\n",ifp->name);
vty_frame (vty, "interface %s\n",ifp->name);
if (ifp->desc)
vty_out (vty, " description %s\n",ifp->desc);
babel_interface_nfo *babel_ifp = babel_get_if_nfo (ifp);
@ -1377,7 +1377,7 @@ interface_config_write (struct vty *vty)
write++;
}
}
vty_out (vty, "!\n");
vty_endframe (vty, "!\n");
write++;
}
return write;

View File

@ -50,11 +50,6 @@ struct vni_walk_ctx {
json_object *json;
};
struct evpn_config_write {
int write;
struct vty *vty;
};
#if defined(HAVE_CUMULUS)
static void display_import_rt(struct vty *vty, struct irt_node *irt,
json_object *json)
@ -587,155 +582,150 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
continue;
if ((table = rn->info) != NULL) {
rd_header = 1;
if ((table = rn->info) == NULL)
continue;
for (rm = bgp_table_top(table); rm;
rm = bgp_route_next(rm))
for (ri = rm->info; ri; ri = ri->next) {
total_count++;
if (type == bgp_show_type_neighbor) {
union sockunion *su =
output_arg;
rd_header = 1;
if (ri->peer->su_remote == NULL
|| !sockunion_same(
ri->peer->su_remote,
su))
continue;
}
if (header == 0) {
if (use_json) {
if (option
== SHOW_DISPLAY_TAGS) {
json_object_int_add(
json,
"bgpTableVersion",
0);
json_object_string_add(
json,
"bgpLocalRouterId",
inet_ntoa(
bgp->router_id));
json_object_object_add(
json,
"bgpStatusCodes",
json_scode);
json_object_object_add(
json,
"bgpOriginCodes",
json_ocode);
}
} else {
if (option
== SHOW_DISPLAY_TAGS)
vty_out(vty,
V4_HEADER_TAG);
else if (
option
== SHOW_DISPLAY_OVERLAY)
vty_out(vty,
V4_HEADER_OVERLAY);
else {
vty_out(vty,
"BGP table version is 0, local router ID is %s\n",
inet_ntoa(
bgp->router_id));
vty_out(vty,
"Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
vty_out(vty,
"Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
vty_out(vty,
V4_HEADER);
}
}
header = 0;
}
if (rd_header) {
u_int16_t type;
struct rd_as rd_as;
struct rd_ip rd_ip;
u_char *pnt;
for (rm = bgp_table_top(table); rm;
rm = bgp_route_next(rm))
for (ri = rm->info; ri; ri = ri->next) {
total_count++;
if (type == bgp_show_type_neighbor) {
union sockunion *su =
output_arg;
pnt = rn->p.u.val;
/* Decode RD type. */
type = decode_rd_type(pnt);
/* Decode RD value. */
if (type == RD_TYPE_AS)
decode_rd_as(pnt + 2,
&rd_as);
else if (type == RD_TYPE_AS4)
decode_rd_as4(pnt + 2,
&rd_as);
else if (type == RD_TYPE_IP)
decode_rd_ip(pnt + 2,
&rd_ip);
if (use_json) {
char buffer[BUFSIZ];
if (type == RD_TYPE_AS
|| type == RD_TYPE_AS4)
sprintf(buffer,
"%u:%d",
rd_as.as,
rd_as.val);
else if (type
== RD_TYPE_IP)
sprintf(buffer,
"%s:%d",
inet_ntoa(
rd_ip.ip),
rd_ip.val);
json_object_string_add(
json_nroute,
"routeDistinguisher",
buffer);
} else {
vty_out(vty,
"Route Distinguisher: ");
if (type == RD_TYPE_AS)
vty_out(vty,
"as2 %u:%d",
rd_as.as,
rd_as.val);
else if (type
== RD_TYPE_AS4)
vty_out(vty,
"as4 %u:%d",
rd_as.as,
rd_as.val);
else if (type
== RD_TYPE_IP)
vty_out(vty,
"ip %s:%d",
inet_ntoa(
rd_ip.ip),
rd_ip.val);
vty_out(vty, "\n\n");
}
rd_header = 0;
}
if (use_json)
json_array =
json_object_new_array();
else
json_array = NULL;
if (option == SHOW_DISPLAY_TAGS)
route_vty_out_tag(
vty, &rm->p, ri, 0,
SAFI_EVPN, json_array);
else if (option == SHOW_DISPLAY_OVERLAY)
route_vty_out_overlay(
vty, &rm->p, ri, 0,
json_array);
else
route_vty_out(vty, &rm->p, ri,
0, SAFI_EVPN,
json_array);
output_count++;
if (ri->peer->su_remote == NULL
|| !sockunion_same(
ri->peer->su_remote,
su))
continue;
}
/* XXX json */
}
if (header == 0) {
if (use_json) {
if (option
== SHOW_DISPLAY_TAGS) {
json_object_int_add(
json,
"bgpTableVersion",
0);
json_object_string_add(
json,
"bgpLocalRouterId",
inet_ntoa(
bgp->router_id));
json_object_object_add(
json,
"bgpStatusCodes",
json_scode);
json_object_object_add(
json,
"bgpOriginCodes",
json_ocode);
}
} else {
if (option
== SHOW_DISPLAY_TAGS)
vty_out(vty,
V4_HEADER_TAG);
else if (
option
== SHOW_DISPLAY_OVERLAY)
vty_out(vty,
V4_HEADER_OVERLAY);
else {
vty_out(vty,
"BGP table version is 0, local router ID is %s\n",
inet_ntoa(
bgp->router_id));
vty_out(vty,
"Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
vty_out(vty,
"Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
vty_out(vty,
V4_HEADER);
}
}
header = 0;
}
if (rd_header) {
u_int16_t type;
struct rd_as rd_as;
struct rd_ip rd_ip;
u_char *pnt;
pnt = rn->p.u.val;
/* Decode RD type. */
type = decode_rd_type(pnt);
/* Decode RD value. */
if (type == RD_TYPE_AS)
decode_rd_as(pnt + 2, &rd_as);
else if (type == RD_TYPE_AS4)
decode_rd_as4(pnt + 2, &rd_as);
else if (type == RD_TYPE_IP)
decode_rd_ip(pnt + 2, &rd_ip);
if (use_json) {
char buffer[BUFSIZ];
if (type == RD_TYPE_AS
|| type == RD_TYPE_AS4)
sprintf(buffer,
"%u:%d",
rd_as.as,
rd_as.val);
else if (type
== RD_TYPE_IP)
sprintf(buffer,
"%s:%d",
inet_ntoa(
rd_ip.ip),
rd_ip.val);
json_object_string_add(
json_nroute,
"routeDistinguisher",
buffer);
} else {
vty_out(vty,
"Route Distinguisher: ");
if (type == RD_TYPE_AS)
vty_out(vty,
"as2 %u:%d",
rd_as.as,
rd_as.val);
else if (type
== RD_TYPE_AS4)
vty_out(vty,
"as4 %u:%d",
rd_as.as,
rd_as.val);
else if (type
== RD_TYPE_IP)
vty_out(vty,
"ip %s:%d",
inet_ntoa(
rd_ip.ip),
rd_ip.val);
vty_out(vty, "\n\n");
}
rd_header = 0;
}
if (use_json)
json_array = json_object_new_array();
else
json_array = NULL;
if (option == SHOW_DISPLAY_TAGS)
route_vty_out_tag(vty, &rm->p, ri, 0,
SAFI_EVPN,
json_array);
else if (option == SHOW_DISPLAY_OVERLAY)
route_vty_out_overlay(vty, &rm->p, ri,
0, json_array);
else
route_vty_out(vty, &rm->p, ri, 0,
SAFI_EVPN, json_array);
output_count++;
}
/* XXX json */
}
if (output_count == 0)
vty_out(vty, "No prefixes displayed, %ld exist\n", total_count);
@ -2125,17 +2115,14 @@ static void evpn_unset_advertise_all_vni(struct bgp *bgp)
}
#endif /* HAVE_CUMULUS */
static void write_vni_config(struct vty *vty, struct bgpevpn *vpn, int *write)
static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
{
char buf1[INET6_ADDRSTRLEN];
afi_t afi = AFI_L2VPN;
safi_t safi = SAFI_EVPN;
char *ecom_str;
struct listnode *node, *nnode;
struct ecommunity *ecom;
if (is_vni_configured(vpn)) {
bgp_config_write_family_header(vty, afi, safi, write);
vty_out(vty, " vni %d\n", vpn->vni);
if (is_rd_configured(vpn))
vty_out(vty, " rd %s\n",
@ -2171,10 +2158,10 @@ static void write_vni_config(struct vty *vty, struct bgpevpn *vpn, int *write)
}
static void write_vni_config_for_entry(struct hash_backet *backet,
struct evpn_config_write *cfg)
struct vty *vty)
{
struct bgpevpn *vpn = (struct bgpevpn *)backet->data;
write_vni_config(cfg->vty, vpn, &cfg->write);
write_vni_config(vty, vpn);
}
#if defined(HAVE_CUMULUS)
@ -3326,29 +3313,19 @@ DEFUN (no_bgp_evpn_vni_rt_without_val,
* Output EVPN configuration information.
*/
void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
safi_t safi, int *write)
safi_t safi)
{
struct evpn_config_write cfg;
if (bgp->vnihash) {
cfg.write = *write;
cfg.vty = vty;
if (bgp->vnihash)
hash_iterate(bgp->vnihash,
(void (*)(struct hash_backet *,
void *))write_vni_config_for_entry,
&cfg);
*write = cfg.write;
}
vty);
if (bgp->advertise_all_vni) {
bgp_config_write_family_header(vty, afi, safi, write);
if (bgp->advertise_all_vni)
vty_out(vty, " advertise-all-vni\n");
}
if (bgp->advertise_gw_macip) {
bgp_config_write_family_header(vty, afi, safi, write);
if (bgp->advertise_gw_macip)
vty_out(vty, " advertise-default-gw\n");
}
}
void bgp_ethernetvpn_init(void)

View File

@ -22,7 +22,7 @@
#define _FRR_BGP_EVPN_VTY_H
extern void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp,
afi_t afi, safi_t safi, int *write);
afi_t afi, safi_t safi);
extern void bgp_ethernetvpn_init(void);
#define L2VPN_HELP_STR "Layer 2 Virtual Private Network\n"

File diff suppressed because it is too large Load Diff

View File

@ -369,12 +369,9 @@ extern void bgp_process(struct bgp *, struct bgp_node *, afi_t, safi_t);
* queue element with NULL bgp node.
*/
extern void bgp_add_eoiu_mark(struct bgp *);
extern int bgp_config_write_table_map(struct vty *, struct bgp *, afi_t, safi_t,
int *);
extern int bgp_config_write_network(struct vty *, struct bgp *, afi_t, safi_t,
int *);
extern int bgp_config_write_distance(struct vty *, struct bgp *, afi_t, safi_t,
int *);
extern void bgp_config_write_table_map(struct vty *, struct bgp *, afi_t, safi_t);
extern void bgp_config_write_network(struct vty *, struct bgp *, afi_t, safi_t);
extern void bgp_config_write_distance(struct vty *, struct bgp *, afi_t, safi_t);
extern void bgp_aggregate_increment(struct bgp *, struct prefix *,
struct bgp_info *, afi_t, safi_t);

View File

@ -1279,7 +1279,7 @@ static int bgp_update_delay_deconfig_vty(struct vty *vty)
return CMD_SUCCESS;
}
int bgp_config_write_update_delay(struct vty *vty, struct bgp *bgp)
void bgp_config_write_update_delay(struct vty *vty, struct bgp *bgp)
{
if (bgp->v_update_delay != BGP_UPDATE_DELAY_DEF) {
vty_out(vty, " update-delay %d", bgp->v_update_delay);
@ -1287,8 +1287,6 @@ int bgp_config_write_update_delay(struct vty *vty, struct bgp *bgp)
vty_out(vty, " %d", bgp->v_establish_wait);
vty_out(vty, "\n");
}
return 0;
}
@ -1342,12 +1340,10 @@ static int bgp_wpkt_quanta_config_vty(struct vty *vty, const char *num,
return CMD_SUCCESS;
}
int bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp)
void bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp)
{
if (bgp->wpkt_quanta != BGP_WRITE_PACKET_MAX)
vty_out(vty, " write-quanta %d\n", bgp->wpkt_quanta);
return 0;
}
@ -1374,12 +1370,10 @@ DEFUN (no_bgp_wpkt_quanta,
return bgp_wpkt_quanta_config_vty(vty, argv[idx_number]->arg, 0);
}
int bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp)
void bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp)
{
if (bgp->coalesce_time != BGP_DEFAULT_SUBGROUP_COALESCE_TIME)
vty_out(vty, " coalesce-time %u\n", bgp->coalesce_time);
return 0;
}
@ -1503,17 +1497,15 @@ ALIAS_HIDDEN(no_bgp_maxpaths_ibgp, no_bgp_maxpaths_ibgp_hidden_cmd,
"Number of paths\n"
"Match the cluster length\n")
int bgp_config_write_maxpaths(struct vty *vty, struct bgp *bgp, afi_t afi,
safi_t safi, int *write)
void bgp_config_write_maxpaths(struct vty *vty, struct bgp *bgp, afi_t afi,
safi_t safi)
{
if (bgp->maxpaths[afi][safi].maxpaths_ebgp != MULTIPATH_NUM) {
bgp_config_write_family_header(vty, afi, safi, write);
vty_out(vty, " maximum-paths %d\n",
bgp->maxpaths[afi][safi].maxpaths_ebgp);
}
if (bgp->maxpaths[afi][safi].maxpaths_ibgp != MULTIPATH_NUM) {
bgp_config_write_family_header(vty, afi, safi, write);
vty_out(vty, " maximum-paths ibgp %d",
bgp->maxpaths[afi][safi].maxpaths_ibgp);
if (CHECK_FLAG(bgp->maxpaths[afi][safi].ibgp_flags,
@ -1521,8 +1513,6 @@ int bgp_config_write_maxpaths(struct vty *vty, struct bgp *bgp, afi_t afi,
vty_out(vty, " equal-cluster-length");
vty_out(vty, "\n");
}
return 0;
}
/* BGP timers. */
@ -2459,7 +2449,7 @@ DEFUN (no_bgp_listen_range,
return bgp_vty_return(vty, ret);
}
int bgp_config_write_listen(struct vty *vty, struct bgp *bgp)
void bgp_config_write_listen(struct vty *vty, struct bgp *bgp)
{
struct peer_group *group;
struct listnode *node, *nnode, *rnode, *nrnode;
@ -2482,8 +2472,6 @@ int bgp_config_write_listen(struct vty *vty, struct bgp *bgp)
}
}
}
return 0;
}
@ -6675,368 +6663,369 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
continue;
if (peer->afc[afi][safi]) {
if (!count) {
unsigned long ents;
char memstrbuf[MTYPE_MEMSTR_LEN];
int vrf_id_ui;
if (!peer->afc[afi][safi])
continue;
vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN)
? -1
: bgp->vrf_id;
if (!count) {
unsigned long ents;
char memstrbuf[MTYPE_MEMSTR_LEN];
int vrf_id_ui;
/* Usage summary and header */
vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN)
? -1
: bgp->vrf_id;
/* Usage summary and header */
if (use_json) {
json_object_string_add(
json, "routerId",
inet_ntoa(bgp->router_id));
json_object_int_add(json, "as",
bgp->as);
json_object_int_add(json, "vrfId",
vrf_id_ui);
json_object_string_add(
json, "vrfName",
(bgp->inst_type
== BGP_INSTANCE_TYPE_DEFAULT)
? "Default"
: bgp->name);
} else {
vty_out(vty,
"BGP router identifier %s, local AS number %u vrf-id %d",
inet_ntoa(bgp->router_id),
bgp->as, vrf_id_ui);
vty_out(vty, "\n");
}
if (bgp_update_delay_configured(bgp)) {
if (use_json) {
json_object_string_add(
json, "routerId",
inet_ntoa(bgp->router_id));
json_object_int_add(json, "as",
bgp->as);
json_object_int_add(json, "vrfId",
vrf_id_ui);
json_object_string_add(
json, "vrfName",
(bgp->inst_type
== BGP_INSTANCE_TYPE_DEFAULT)
? "Default"
: bgp->name);
} else {
vty_out(vty,
"BGP router identifier %s, local AS number %u vrf-id %d",
inet_ntoa(bgp->router_id),
bgp->as, vrf_id_ui);
vty_out(vty, "\n");
}
json_object_int_add(
json,
"updateDelayLimit",
bgp->v_update_delay);
if (bgp_update_delay_configured(bgp)) {
if (use_json) {
if (bgp->v_update_delay
!= bgp->v_establish_wait)
json_object_int_add(
json,
"updateDelayLimit",
bgp->v_update_delay);
"updateDelayEstablishWait",
bgp->v_establish_wait);
if (bgp->v_update_delay
!= bgp->v_establish_wait)
json_object_int_add(
json,
"updateDelayEstablishWait",
bgp->v_establish_wait);
if (bgp_update_delay_active(
bgp)) {
if (bgp_update_delay_active(
bgp)) {
json_object_string_add(
json,
"updateDelayFirstNeighbor",
bgp->update_delay_begin_time);
json_object_boolean_true_add(
json,
"updateDelayInProgress");
} else {
if (bgp->update_delay_over) {
json_object_string_add(
json,
"updateDelayFirstNeighbor",
bgp->update_delay_begin_time);
json_object_boolean_true_add(
json_object_string_add(
json,
"updateDelayInProgress");
} else {
if (bgp->update_delay_over) {
json_object_string_add(
json,
"updateDelayFirstNeighbor",
bgp->update_delay_begin_time);
json_object_string_add(
json,
"updateDelayBestpathResumed",
bgp->update_delay_end_time);
json_object_string_add(
json,
"updateDelayZebraUpdateResume",
bgp->update_delay_zebra_resume_time);
json_object_string_add(
json,
"updateDelayPeerUpdateResume",
bgp->update_delay_peers_resume_time);
}
"updateDelayBestpathResumed",
bgp->update_delay_end_time);
json_object_string_add(
json,
"updateDelayZebraUpdateResume",
bgp->update_delay_zebra_resume_time);
json_object_string_add(
json,
"updateDelayPeerUpdateResume",
bgp->update_delay_peers_resume_time);
}
} else {
}
} else {
vty_out(vty,
"Read-only mode update-delay limit: %d seconds\n",
bgp->v_update_delay);
if (bgp->v_update_delay
!= bgp->v_establish_wait)
vty_out(vty,
"Read-only mode update-delay limit: %d seconds\n",
bgp->v_update_delay);
if (bgp->v_update_delay
!= bgp->v_establish_wait)
vty_out(vty,
" Establish wait: %d seconds\n",
bgp->v_establish_wait);
" Establish wait: %d seconds\n",
bgp->v_establish_wait);
if (bgp_update_delay_active(
bgp)) {
if (bgp_update_delay_active(
bgp)) {
vty_out(vty,
" First neighbor established: %s\n",
bgp->update_delay_begin_time);
vty_out(vty,
" Delay in progress\n");
} else {
if (bgp->update_delay_over) {
vty_out(vty,
" First neighbor established: %s\n",
bgp->update_delay_begin_time);
vty_out(vty,
" Delay in progress\n");
} else {
if (bgp->update_delay_over) {
vty_out(vty,
" First neighbor established: %s\n",
bgp->update_delay_begin_time);
vty_out(vty,
" Best-paths resumed: %s\n",
bgp->update_delay_end_time);
vty_out(vty,
" zebra update resumed: %s\n",
bgp->update_delay_zebra_resume_time);
vty_out(vty,
" peers update resumed: %s\n",
bgp->update_delay_peers_resume_time);
}
" Best-paths resumed: %s\n",
bgp->update_delay_end_time);
vty_out(vty,
" zebra update resumed: %s\n",
bgp->update_delay_zebra_resume_time);
vty_out(vty,
" peers update resumed: %s\n",
bgp->update_delay_peers_resume_time);
}
}
}
if (use_json) {
if (bgp_maxmed_onstartup_configured(bgp)
&& bgp->maxmed_active)
json_object_boolean_true_add(
json,
"maxMedOnStartup");
if (bgp->v_maxmed_admin)
json_object_boolean_true_add(
json,
"maxMedAdministrative");
json_object_int_add(
json, "tableVersion",
bgp_table_version(
bgp->rib[afi][safi]));
ents = bgp_table_count(
bgp->rib[afi][safi]);
json_object_int_add(json, "ribCount",
ents);
json_object_int_add(
json, "ribMemory",
ents * sizeof(struct bgp_node));
ents = listcount(bgp->peer);
json_object_int_add(json, "peerCount",
ents);
json_object_int_add(
json, "peerMemory",
ents * sizeof(struct peer));
if ((ents = listcount(bgp->group))) {
json_object_int_add(
json, "peerGroupCount",
ents);
json_object_int_add(
json, "peerGroupMemory",
ents * sizeof(struct
peer_group));
}
if (CHECK_FLAG(bgp->af_flags[afi][safi],
BGP_CONFIG_DAMPENING))
json_object_boolean_true_add(
json,
"dampeningEnabled");
} else {
if (bgp_maxmed_onstartup_configured(bgp)
&& bgp->maxmed_active)
vty_out(vty,
"Max-med on-startup active\n");
if (bgp->v_maxmed_admin)
vty_out(vty,
"Max-med administrative active\n");
vty_out(vty,
"BGP table version %" PRIu64
"\n",
bgp_table_version(
bgp->rib[afi][safi]));
ents = bgp_table_count(
bgp->rib[afi][safi]);
vty_out(vty,
"RIB entries %ld, using %s of memory\n",
ents,
mtype_memstr(
memstrbuf,
sizeof(memstrbuf),
ents * sizeof(struct
bgp_node)));
/* Peer related usage */
ents = listcount(bgp->peer);
vty_out(vty,
"Peers %ld, using %s of memory\n",
ents,
mtype_memstr(
memstrbuf,
sizeof(memstrbuf),
ents * sizeof(struct
peer)));
if ((ents = listcount(bgp->group)))
vty_out(vty,
"Peer groups %ld, using %s of memory\n",
ents,
mtype_memstr(
memstrbuf,
sizeof(memstrbuf),
ents * sizeof(struct
peer_group)));
if (CHECK_FLAG(bgp->af_flags[afi][safi],
BGP_CONFIG_DAMPENING))
vty_out(vty,
"Dampening enabled.\n");
vty_out(vty, "\n");
/* Subtract 8 here because 'Neighbor' is
* 8 characters */
vty_out(vty, "Neighbor");
vty_out(vty, "%*s",
max_neighbor_width - 8, " ");
vty_out(vty,
"V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd\n");
}
}
count++;
if (use_json) {
json_peer = json_object_new_object();
if (peer_dynamic_neighbor(peer))
if (bgp_maxmed_onstartup_configured(bgp)
&& bgp->maxmed_active)
json_object_boolean_true_add(
json_peer, "dynamicPeer");
json,
"maxMedOnStartup");
if (bgp->v_maxmed_admin)
json_object_boolean_true_add(
json,
"maxMedAdministrative");
if (peer->hostname)
json_object_string_add(json_peer,
"hostname",
peer->hostname);
if (peer->domainname)
json_object_string_add(
json_peer, "domainname",
peer->domainname);
json_object_int_add(json_peer, "remoteAs",
peer->as);
json_object_int_add(json_peer, "version", 4);
json_object_int_add(
json_peer, "msgRcvd",
peer->open_in + peer->update_in
+ peer->keepalive_in
+ peer->notify_in
+ peer->refresh_in
+ peer->dynamic_cap_in);
json, "tableVersion",
bgp_table_version(
bgp->rib[afi][safi]));
ents = bgp_table_count(
bgp->rib[afi][safi]);
json_object_int_add(json, "ribCount",
ents);
json_object_int_add(
json_peer, "msgSent",
peer->open_out + peer->update_out
+ peer->keepalive_out
+ peer->notify_out
+ peer->refresh_out
+ peer->dynamic_cap_out);
json, "ribMemory",
ents * sizeof(struct bgp_node));
json_object_int_add(json_peer, "tableVersion",
peer->version[afi][safi]);
json_object_int_add(json_peer, "outq",
peer->obuf->count);
json_object_int_add(json_peer, "inq", 0);
peer_uptime(peer->uptime, timebuf,
BGP_UPTIME_LEN, use_json,
json_peer);
ents = listcount(bgp->peer);
json_object_int_add(json, "peerCount",
ents);
json_object_int_add(
json_peer, "prefixReceivedCount",
peer->pcount[afi][pfx_rcd_safi]);
json, "peerMemory",
ents * sizeof(struct peer));
if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN))
json_object_string_add(json_peer,
"state",
"Idle (Admin)");
else if (CHECK_FLAG(
peer->sflags,
PEER_STATUS_PREFIX_OVERFLOW))
json_object_string_add(json_peer,
"state",
"Idle (PfxCt)");
else
json_object_string_add(
json_peer, "state",
lookup_msg(bgp_status_msg,
peer->status, NULL));
if ((ents = listcount(bgp->group))) {
json_object_int_add(
json, "peerGroupCount",
ents);
json_object_int_add(
json, "peerGroupMemory",
ents * sizeof(struct
peer_group));
}
if (peer->conf_if)
json_object_string_add(json_peer,
"idType",
"interface");
else if (peer->su.sa.sa_family == AF_INET)
json_object_string_add(
json_peer, "idType", "ipv4");
else if (peer->su.sa.sa_family == AF_INET6)
json_object_string_add(
json_peer, "idType", "ipv6");
json_object_object_add(json_peers, peer->host,
json_peer);
if (CHECK_FLAG(bgp->af_flags[afi][safi],
BGP_CONFIG_DAMPENING))
json_object_boolean_true_add(
json,
"dampeningEnabled");
} else {
memset(dn_flag, '\0', sizeof(dn_flag));
if (peer_dynamic_neighbor(peer)) {
dn_count++;
dn_flag[0] = '*';
}
if (bgp_maxmed_onstartup_configured(bgp)
&& bgp->maxmed_active)
vty_out(vty,
"Max-med on-startup active\n");
if (bgp->v_maxmed_admin)
vty_out(vty,
"Max-med administrative active\n");
if (peer->hostname
&& bgp_flag_check(bgp,
BGP_FLAG_SHOW_HOSTNAME))
len = vty_out(vty, "%s%s(%s)", dn_flag,
peer->hostname,
peer->host);
else
len = vty_out(vty, "%s%s", dn_flag,
peer->host);
vty_out(vty,
"BGP table version %" PRIu64
"\n",
bgp_table_version(
bgp->rib[afi][safi]));
/* pad the neighbor column with spaces */
if (len < max_neighbor_width)
vty_out(vty, "%*s",
max_neighbor_width - len, " ");
ents = bgp_table_count(
bgp->rib[afi][safi]);
vty_out(vty,
"RIB entries %ld, using %s of memory\n",
ents,
mtype_memstr(
memstrbuf,
sizeof(memstrbuf),
ents * sizeof(struct
bgp_node)));
vty_out(vty, "4 %10u %7d %7d %8" PRIu64
" %4d %4zd %8s",
peer->as,
peer->open_in + peer->update_in
+ peer->keepalive_in
+ peer->notify_in
+ peer->refresh_in
+ peer->dynamic_cap_in,
peer->open_out + peer->update_out
+ peer->keepalive_out
+ peer->notify_out
+ peer->refresh_out
+ peer->dynamic_cap_out,
peer->version[afi][safi], 0,
peer->obuf->count,
peer_uptime(peer->uptime, timebuf,
BGP_UPTIME_LEN, 0, NULL));
/* Peer related usage */
ents = listcount(bgp->peer);
vty_out(vty,
"Peers %ld, using %s of memory\n",
ents,
mtype_memstr(
memstrbuf,
sizeof(memstrbuf),
ents * sizeof(struct
peer)));
if (peer->status == Established)
vty_out(vty, " %12ld",
peer->pcount[afi]
[pfx_rcd_safi]);
else {
if (CHECK_FLAG(peer->flags,
PEER_FLAG_SHUTDOWN))
vty_out(vty, " Idle (Admin)");
else if (
CHECK_FLAG(
peer->sflags,
PEER_STATUS_PREFIX_OVERFLOW))
vty_out(vty, " Idle (PfxCt)");
else
vty_out(vty, " %12s",
lookup_msg(
bgp_status_msg,
peer->status,
NULL));
}
if ((ents = listcount(bgp->group)))
vty_out(vty,
"Peer groups %ld, using %s of memory\n",
ents,
mtype_memstr(
memstrbuf,
sizeof(memstrbuf),
ents * sizeof(struct
peer_group)));
if (CHECK_FLAG(bgp->af_flags[afi][safi],
BGP_CONFIG_DAMPENING))
vty_out(vty,
"Dampening enabled.\n");
vty_out(vty, "\n");
/* Subtract 8 here because 'Neighbor' is
* 8 characters */
vty_out(vty, "Neighbor");
vty_out(vty, "%*s",
max_neighbor_width - 8, " ");
vty_out(vty,
"V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd\n");
}
}
count++;
if (use_json) {
json_peer = json_object_new_object();
if (peer_dynamic_neighbor(peer))
json_object_boolean_true_add(
json_peer, "dynamicPeer");
if (peer->hostname)
json_object_string_add(json_peer,
"hostname",
peer->hostname);
if (peer->domainname)
json_object_string_add(
json_peer, "domainname",
peer->domainname);
json_object_int_add(json_peer, "remoteAs",
peer->as);
json_object_int_add(json_peer, "version", 4);
json_object_int_add(
json_peer, "msgRcvd",
peer->open_in + peer->update_in
+ peer->keepalive_in
+ peer->notify_in
+ peer->refresh_in
+ peer->dynamic_cap_in);
json_object_int_add(
json_peer, "msgSent",
peer->open_out + peer->update_out
+ peer->keepalive_out
+ peer->notify_out
+ peer->refresh_out
+ peer->dynamic_cap_out);
json_object_int_add(json_peer, "tableVersion",
peer->version[afi][safi]);
json_object_int_add(json_peer, "outq",
peer->obuf->count);
json_object_int_add(json_peer, "inq", 0);
peer_uptime(peer->uptime, timebuf,
BGP_UPTIME_LEN, use_json,
json_peer);
json_object_int_add(
json_peer, "prefixReceivedCount",
peer->pcount[afi][pfx_rcd_safi]);
if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN))
json_object_string_add(json_peer,
"state",
"Idle (Admin)");
else if (CHECK_FLAG(
peer->sflags,
PEER_STATUS_PREFIX_OVERFLOW))
json_object_string_add(json_peer,
"state",
"Idle (PfxCt)");
else
json_object_string_add(
json_peer, "state",
lookup_msg(bgp_status_msg,
peer->status, NULL));
if (peer->conf_if)
json_object_string_add(json_peer,
"idType",
"interface");
else if (peer->su.sa.sa_family == AF_INET)
json_object_string_add(
json_peer, "idType", "ipv4");
else if (peer->su.sa.sa_family == AF_INET6)
json_object_string_add(
json_peer, "idType", "ipv6");
json_object_object_add(json_peers, peer->host,
json_peer);
} else {
memset(dn_flag, '\0', sizeof(dn_flag));
if (peer_dynamic_neighbor(peer)) {
dn_count++;
dn_flag[0] = '*';
}
if (peer->hostname
&& bgp_flag_check(bgp,
BGP_FLAG_SHOW_HOSTNAME))
len = vty_out(vty, "%s%s(%s)", dn_flag,
peer->hostname,
peer->host);
else
len = vty_out(vty, "%s%s", dn_flag,
peer->host);
/* pad the neighbor column with spaces */
if (len < max_neighbor_width)
vty_out(vty, "%*s",
max_neighbor_width - len, " ");
vty_out(vty, "4 %10u %7d %7d %8" PRIu64
" %4d %4zd %8s",
peer->as,
peer->open_in + peer->update_in
+ peer->keepalive_in
+ peer->notify_in
+ peer->refresh_in
+ peer->dynamic_cap_in,
peer->open_out + peer->update_out
+ peer->keepalive_out
+ peer->notify_out
+ peer->refresh_out
+ peer->dynamic_cap_out,
peer->version[afi][safi], 0,
peer->obuf->count,
peer_uptime(peer->uptime, timebuf,
BGP_UPTIME_LEN, 0, NULL));
if (peer->status == Established)
vty_out(vty, " %12ld",
peer->pcount[afi]
[pfx_rcd_safi]);
else {
if (CHECK_FLAG(peer->flags,
PEER_FLAG_SHUTDOWN))
vty_out(vty, " Idle (Admin)");
else if (
CHECK_FLAG(
peer->sflags,
PEER_STATUS_PREFIX_OVERFLOW))
vty_out(vty, " Idle (PfxCt)");
else
vty_out(vty, " %12s",
lookup_msg(
bgp_status_msg,
peer->status,
NULL));
}
vty_out(vty, "\n");
}
}
if (use_json) {
@ -11156,14 +11145,14 @@ DEFUN (no_bgp_redistribute_ipv6,
return bgp_redistribute_unset(bgp, AFI_IP6, type, 0);
}
int bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi,
safi_t safi, int *write)
void bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi,
safi_t safi)
{
int i;
/* Unicast redistribution only. */
if (safi != SAFI_UNICAST)
return 0;
return;
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
/* Redistribute BGP does not make sense. */
@ -11177,11 +11166,6 @@ int bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi,
continue;
for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
/* Display "address-family" when it is not yet
* diplayed. */
bgp_config_write_family_header(vty, afi, safi,
write);
/* "redistribute" configuration. */
vty_out(vty, " redistribute %s",
zebra_route_string(i));
@ -11197,7 +11181,6 @@ int bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi,
}
}
}
return *write;
}
/* BGP node structure. */

View File

@ -46,10 +46,10 @@ struct bgp;
extern void bgp_vty_init(void);
extern const char *afi_safi_print(afi_t, safi_t);
extern const char *afi_safi_json(afi_t, safi_t);
extern int bgp_config_write_update_delay(struct vty *, struct bgp *);
extern int bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp);
extern int bgp_config_write_listen(struct vty *vty, struct bgp *bgp);
extern int bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp);
extern void bgp_config_write_update_delay(struct vty *, struct bgp *);
extern void bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp);
extern void bgp_config_write_listen(struct vty *vty, struct bgp *bgp);
extern void bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp);
extern int bgp_vty_return(struct vty *vty, int ret);
extern struct peer *peer_and_group_lookup_vty(struct vty *vty,
const char *peer_str);

View File

@ -26,10 +26,10 @@
extern void bgp_zebra_init(struct thread_master *master);
extern void bgp_zebra_destroy(void);
extern int bgp_if_update_all(void);
extern int bgp_config_write_maxpaths(struct vty *, struct bgp *, afi_t, safi_t,
int *);
extern int bgp_config_write_redistribute(struct vty *, struct bgp *, afi_t,
safi_t, int *);
extern void bgp_config_write_maxpaths(struct vty *, struct bgp *, afi_t,
safi_t);
extern void bgp_config_write_redistribute(struct vty *, struct bgp *, afi_t,
safi_t);
extern void bgp_zebra_announce(struct bgp_node *, struct prefix *,
struct bgp_info *, struct bgp *, afi_t, safi_t);
extern void bgp_zebra_announce_table(struct bgp *, afi_t, safi_t);

View File

@ -6204,14 +6204,8 @@ char *peer_uptime(time_t uptime2, char *buf, size_t len, u_char use_json,
return buf;
}
#define afi_header_vty_out(vty, afi, safi, write, format, ...) \
do { \
bgp_config_write_family_header(vty, afi, safi, write); \
vty_out(vty, format, ## __VA_ARGS__); \
} while (0)
static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
afi_t afi, safi_t safi, int *write)
afi_t afi, safi_t safi)
{
struct bgp_filter *filter;
struct bgp_filter *gfilter = NULL;
@ -6230,16 +6224,13 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
if (!gfilter || !gfilter->dlist[in].name
|| strcmp(filter->dlist[in].name, gfilter->dlist[in].name)
!= 0) {
afi_header_vty_out(
vty, afi, safi, write,
" neighbor %s distribute-list %s in\n", addr,
filter->dlist[in].name);
vty_out(vty, " neighbor %s distribute-list %s in\n",
addr, filter->dlist[in].name);
}
if (filter->dlist[out].name && !gfilter) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s distribute-list %s out\n",
addr, filter->dlist[out].name);
vty_out(vty, " neighbor %s distribute-list %s out\n", addr,
filter->dlist[out].name);
}
/* prefix-list. */
@ -6247,19 +6238,17 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
if (!gfilter || !gfilter->plist[in].name
|| strcmp(filter->plist[in].name, gfilter->plist[in].name)
!= 0) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s prefix-list %s in\n",
addr, filter->plist[in].name);
vty_out(vty, " neighbor %s prefix-list %s in\n", addr,
filter->plist[in].name);
}
if (filter->plist[out].name)
if (!gfilter || !gfilter->plist[out].name
|| strcmp(filter->plist[out].name, gfilter->plist[out].name)
!= 0) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s prefix-list %s out\n",
addr, filter->plist[out].name);
}
if (filter->plist[out].name)
if (!gfilter || !gfilter->plist[out].name
|| strcmp(filter->plist[out].name, gfilter->plist[out].name)
!= 0) {
vty_out(vty, " neighbor %s prefix-list %s out\n", addr,
filter->plist[out].name);
}
/* route-map. */
if (filter->map[RMAP_IN].name)
@ -6267,9 +6256,8 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
|| strcmp(filter->map[RMAP_IN].name,
gfilter->map[RMAP_IN].name)
!= 0) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s route-map %s in\n",
addr, filter->map[RMAP_IN].name);
vty_out(vty, " neighbor %s route-map %s in\n", addr,
filter->map[RMAP_IN].name);
}
if (filter->map[RMAP_OUT].name)
@ -6277,16 +6265,14 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
|| strcmp(filter->map[RMAP_OUT].name,
gfilter->map[RMAP_OUT].name)
!= 0) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s route-map %s out\n",
addr, filter->map[RMAP_OUT].name);
vty_out(vty, " neighbor %s route-map %s out\n", addr,
filter->map[RMAP_OUT].name);
}
/* unsuppress-map */
if (filter->usmap.name && !gfilter) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s unsuppress-map %s\n", addr,
filter->usmap.name);
vty_out(vty, " neighbor %s unsuppress-map %s\n", addr,
filter->usmap.name);
}
/* filter-list. */
@ -6294,15 +6280,13 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
if (!gfilter || !gfilter->aslist[in].name
|| strcmp(filter->aslist[in].name, gfilter->aslist[in].name)
!= 0) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s filter-list %s in\n",
addr, filter->aslist[in].name);
vty_out(vty, " neighbor %s filter-list %s in\n", addr,
filter->aslist[in].name);
}
if (filter->aslist[out].name && !gfilter) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s filter-list %s out\n", addr,
filter->aslist[out].name);
vty_out(vty, " neighbor %s filter-list %s out\n", addr,
filter->aslist[out].name);
}
}
@ -6622,8 +6606,7 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
/* BGP peer configuration display function. */
static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
struct peer *peer, afi_t afi, safi_t safi,
int *write)
struct peer *peer, afi_t afi, safi_t safi)
{
struct peer *g_peer = NULL;
char *addr;
@ -6646,36 +6629,29 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
/* If the peer-group is active but peer is not, print a 'no
* activate' */
if (g_peer->afc[afi][safi] && !peer->afc[afi][safi]) {
afi_header_vty_out(vty, afi, safi, write,
" no neighbor %s activate\n", addr);
vty_out(vty, " no neighbor %s activate\n", addr);
}
/* If the peer-group is not active but peer is, print an
'activate' */
else if (!g_peer->afc[afi][safi] && peer->afc[afi][safi]) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s activate\n", addr);
vty_out(vty, " neighbor %s activate\n", addr);
}
} else {
if (peer->afc[afi][safi]) {
if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
if (bgp_flag_check(bgp,
BGP_FLAG_NO_DEFAULT_IPV4)) {
afi_header_vty_out(
vty, afi, safi, write,
" neighbor %s activate\n",
vty_out(vty, " neighbor %s activate\n",
addr);
}
} else
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s activate\n",
addr);
vty_out(vty, " neighbor %s activate\n", addr);
} else {
if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
if (!bgp_flag_check(bgp,
BGP_FLAG_NO_DEFAULT_IPV4)) {
afi_header_vty_out(
vty, afi, safi, write,
vty_out(vty,
" no neighbor %s activate\n",
addr);
}
@ -6686,25 +6662,20 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
/* addpath TX knobs */
if (peergroup_af_flag_check(peer, afi, safi,
PEER_FLAG_ADDPATH_TX_ALL_PATHS)) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s addpath-tx-all-paths\n",
addr);
vty_out(vty, " neighbor %s addpath-tx-all-paths\n", addr);
}
if (peergroup_af_flag_check(peer, afi, safi,
PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s addpath-tx-bestpath-per-AS\n",
addr);
vty_out(vty, " neighbor %s addpath-tx-bestpath-per-AS\n",
addr);
}
/* ORF capability. */
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM)
|| peergroup_af_flag_check(peer, afi, safi,
PEER_FLAG_ORF_PREFIX_RM)) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s capability orf prefix-list",
addr);
vty_out(vty, " neighbor %s capability orf prefix-list", addr);
if (peergroup_af_flag_check(peer, afi, safi,
PEER_FLAG_ORF_PREFIX_SM)
@ -6722,57 +6693,46 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
/* Route reflector client. */
if (peergroup_af_flag_check(peer, afi, safi,
PEER_FLAG_REFLECTOR_CLIENT)) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s route-reflector-client\n",
addr);
vty_out(vty, " neighbor %s route-reflector-client\n", addr);
}
/* next-hop-self force */
if (peergroup_af_flag_check(peer, afi, safi,
PEER_FLAG_FORCE_NEXTHOP_SELF)) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s next-hop-self force\n", addr);
vty_out(vty, " neighbor %s next-hop-self force\n", addr);
}
/* next-hop-self */
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s next-hop-self\n", addr);
vty_out(vty, " neighbor %s next-hop-self\n", addr);
}
/* remove-private-AS */
if (peergroup_af_flag_check(peer, afi, safi,
PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) {
afi_header_vty_out(
vty, afi, safi, write,
" neighbor %s remove-private-AS all replace-AS\n",
vty_out(vty, " neighbor %s remove-private-AS all replace-AS\n",
addr);
}
else if (peergroup_af_flag_check(peer, afi, safi,
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) {
afi_header_vty_out(
vty, afi, safi, write,
" neighbor %s remove-private-AS replace-AS\n", addr);
vty_out(vty, " neighbor %s remove-private-AS replace-AS\n",
addr);
}
else if (peergroup_af_flag_check(peer, afi, safi,
PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s remove-private-AS all\n",
addr);
vty_out(vty, " neighbor %s remove-private-AS all\n", addr);
}
else if (peergroup_af_flag_check(peer, afi, safi,
PEER_FLAG_REMOVE_PRIVATE_AS)) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s remove-private-AS\n", addr);
vty_out(vty, " neighbor %s remove-private-AS\n", addr);
}
/* as-override */
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s as-override\n", addr);
vty_out(vty, " neighbor %s as-override\n", addr);
}
/* send-community print. */
@ -6784,27 +6744,21 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
&& peergroup_af_flag_check(
peer, afi, safi,
PEER_FLAG_SEND_LARGE_COMMUNITY)) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s send-community all\n",
addr);
vty_out(vty, " neighbor %s send-community all\n",
addr);
} else if (peergroup_af_flag_check(
peer, afi, safi,
PEER_FLAG_SEND_LARGE_COMMUNITY)) {
afi_header_vty_out(
vty, afi, safi, write,
" neighbor %s send-community large\n", addr);
vty_out(vty, " neighbor %s send-community large\n",
addr);
} else if (peergroup_af_flag_check(
peer, afi, safi,
PEER_FLAG_SEND_EXT_COMMUNITY)) {
afi_header_vty_out(
vty, afi, safi, write,
" neighbor %s send-community extended\n",
vty_out(vty, " neighbor %s send-community extended\n",
addr);
} else if (peergroup_af_flag_check(peer, afi, safi,
PEER_FLAG_SEND_COMMUNITY)) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s send-community\n",
addr);
vty_out(vty, " neighbor %s send-community\n", addr);
}
} else {
if (!peer_af_flag_check(peer, afi, safi,
@ -6821,9 +6775,8 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
&& (!g_peer || peer_af_flag_check(
g_peer, afi, safi,
PEER_FLAG_SEND_LARGE_COMMUNITY))) {
afi_header_vty_out(
vty, afi, safi, write,
" no neighbor %s send-community all\n", addr);
vty_out(vty, " no neighbor %s send-community all\n",
addr);
} else {
if (!peer_af_flag_check(peer, afi, safi,
PEER_FLAG_SEND_LARGE_COMMUNITY)
@ -6831,8 +6784,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|| peer_af_flag_check(
g_peer, afi, safi,
PEER_FLAG_SEND_LARGE_COMMUNITY))) {
afi_header_vty_out(
vty, afi, safi, write,
vty_out(vty,
" no neighbor %s send-community large\n",
addr);
}
@ -6843,8 +6795,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|| peer_af_flag_check(
g_peer, afi, safi,
PEER_FLAG_SEND_EXT_COMMUNITY))) {
afi_header_vty_out(
vty, afi, safi, write,
vty_out(vty,
" no neighbor %s send-community extended\n",
addr);
}
@ -6854,8 +6805,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
&& (!g_peer || peer_af_flag_check(
g_peer, afi, safi,
PEER_FLAG_SEND_COMMUNITY))) {
afi_header_vty_out(
vty, afi, safi, write,
vty_out(vty,
" no neighbor %s send-community\n",
addr);
}
@ -6873,8 +6823,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|| (peer->default_rmap[afi][safi].name
&& strcmp(peer->default_rmap[afi][safi].name,
g_peer->default_rmap[afi][safi].name))))) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s default-originate", addr);
vty_out(vty, " neighbor %s default-originate", addr);
if (peer->default_rmap[afi][safi].name)
vty_out(vty, " route-map %s",
peer->default_rmap[afi][safi].name);
@ -6883,9 +6832,8 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
/* Soft reconfiguration inbound. */
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_SOFT_RECONFIG)) {
afi_header_vty_out(
vty, afi, safi, write,
" neighbor %s soft-reconfiguration inbound\n", addr);
vty_out(vty, " neighbor %s soft-reconfiguration inbound\n",
addr);
}
/* maximum-prefix. */
@ -6898,9 +6846,8 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
PEER_FLAG_MAX_PREFIX_WARNING)
!= CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_MAX_PREFIX_WARNING)) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s maximum-prefix %lu",
addr, peer->pmax[afi][safi]);
vty_out(vty, " neighbor %s maximum-prefix %lu", addr,
peer->pmax[afi][safi]);
if (peer->pmax_threshold[afi][safi]
!= MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
vty_out(vty, " %u",
@ -6917,16 +6864,13 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
/* Route server client. */
if (peergroup_af_flag_check(peer, afi, safi,
PEER_FLAG_RSERVER_CLIENT)) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s route-server-client\n", addr);
vty_out(vty, " neighbor %s route-server-client\n", addr);
}
/* Nexthop-local unchanged. */
if (peergroup_af_flag_check(peer, afi, safi,
PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s nexthop-local unchanged\n",
addr);
vty_out(vty, " neighbor %s nexthop-local unchanged\n", addr);
}
/* allowas-in <1-10> */
@ -6937,14 +6881,11 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|| peer->allowas_in[afi][safi]
!= g_peer->allowas_in[afi][safi]) {
if (peer->allowas_in[afi][safi] == 3) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s allowas-in\n",
addr);
vty_out(vty, " neighbor %s allowas-in\n",
addr);
} else {
afi_header_vty_out(
vty, afi, safi, write,
" neighbor %s allowas-in %d\n", addr,
peer->allowas_in[afi][safi]);
vty_out(vty, " neighbor %s allowas-in %d\n",
addr, peer->allowas_in[afi][safi]);
}
}
}
@ -6955,9 +6896,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
if (!peer_group_active(peer)
|| !peer_af_flag_check(g_peer, afi, safi,
PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s allowas-in origin\n",
addr);
vty_out(vty, " neighbor %s allowas-in origin\n", addr);
}
}
@ -6967,15 +6906,13 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|| !peer_af_flag_check(g_peer, afi, safi, PEER_FLAG_WEIGHT)
|| peer->weight[afi][safi] != g_peer->weight[afi][safi]) {
if (peer->weight[afi][safi]) {
afi_header_vty_out(vty, afi, safi, write,
" neighbor %s weight %lu\n",
addr,
peer->weight[afi][safi]);
vty_out(vty, " neighbor %s weight %lu\n", addr,
peer->weight[afi][safi]);
}
}
/* Filter. */
bgp_config_write_filter(vty, peer, afi, safi, write);
bgp_config_write_filter(vty, peer, afi, safi);
/* atribute-unchanged. */
if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) ||
@ -6990,8 +6927,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
peergroup_af_flag_check(peer, afi, safi,
PEER_FLAG_MED_UNCHANGED)) {
afi_header_vty_out(
vty, afi, safi, write,
vty_out(vty,
" neighbor %s attribute-unchanged%s%s%s\n",
addr,
peer_af_flag_check(
@ -7012,64 +6948,52 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
}
}
/* Display "address-family" configuration header. */
void bgp_config_write_family_header(struct vty *vty, afi_t afi, safi_t safi,
int *write)
{
if (*write)
return;
vty_out(vty, " !\n address-family ");
if (afi == AFI_IP) {
if (safi == SAFI_UNICAST)
vty_out(vty, "ipv4 unicast");
else if (safi == SAFI_LABELED_UNICAST)
vty_out(vty, "ipv4 labeled-unicast");
else if (safi == SAFI_MULTICAST)
vty_out(vty, "ipv4 multicast");
else if (safi == SAFI_MPLS_VPN)
vty_out(vty, "ipv4 vpn");
else if (safi == SAFI_ENCAP)
vty_out(vty, "ipv4 encap");
} else if (afi == AFI_IP6) {
if (safi == SAFI_UNICAST)
vty_out(vty, "ipv6 unicast");
else if (safi == SAFI_LABELED_UNICAST)
vty_out(vty, "ipv6 labeled-unicast");
else if (safi == SAFI_MULTICAST)
vty_out(vty, "ipv6 multicast");
else if (safi == SAFI_MPLS_VPN)
vty_out(vty, "ipv6 vpn");
else if (safi == SAFI_ENCAP)
vty_out(vty, "ipv6 encap");
} else if (afi == AFI_L2VPN) {
if (safi == SAFI_EVPN)
vty_out(vty, "l2vpn evpn");
}
vty_out(vty, "\n");
*write = 1;
}
/* Address family based peer configuration display. */
static int bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
safi_t safi)
static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
safi_t safi)
{
int write = 0;
struct peer *peer;
struct peer_group *group;
struct listnode *node, *nnode;
bgp_config_write_distance(vty, bgp, afi, safi, &write);
bgp_config_write_network(vty, bgp, afi, safi, &write);
vty_frame(vty, " !\n address-family ");
if (afi == AFI_IP) {
if (safi == SAFI_UNICAST)
vty_frame(vty, "ipv4 unicast");
else if (safi == SAFI_LABELED_UNICAST)
vty_frame(vty, "ipv4 labeled-unicast");
else if (safi == SAFI_MULTICAST)
vty_frame(vty, "ipv4 multicast");
else if (safi == SAFI_MPLS_VPN)
vty_frame(vty, "ipv4 vpn");
else if (safi == SAFI_ENCAP)
vty_frame(vty, "ipv4 encap");
} else if (afi == AFI_IP6) {
if (safi == SAFI_UNICAST)
vty_frame(vty, "ipv6 unicast");
else if (safi == SAFI_LABELED_UNICAST)
vty_frame(vty, "ipv6 labeled-unicast");
else if (safi == SAFI_MULTICAST)
vty_frame(vty, "ipv6 multicast");
else if (safi == SAFI_MPLS_VPN)
vty_frame(vty, "ipv6 vpn");
else if (safi == SAFI_ENCAP)
vty_frame(vty, "ipv6 encap");
} else if (afi == AFI_L2VPN) {
if (safi == SAFI_EVPN)
vty_frame(vty, "l2vpn evpn");
}
vty_frame(vty, "\n");
bgp_config_write_redistribute(vty, bgp, afi, safi, &write);
bgp_config_write_distance(vty, bgp, afi, safi);
bgp_config_write_network(vty, bgp, afi, safi);
bgp_config_write_redistribute(vty, bgp, afi, safi);
for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi,
&write);
bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi);
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
/* Skip dynamic neighbors. */
@ -7078,20 +7002,16 @@ static int bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
/* Do not display doppelganger peers */
if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
bgp_config_write_peer_af(vty, bgp, peer, afi, safi,
&write);
bgp_config_write_peer_af(vty, bgp, peer, afi, safi);
}
bgp_config_write_maxpaths(vty, bgp, afi, safi, &write);
bgp_config_write_table_map(vty, bgp, afi, safi, &write);
bgp_config_write_maxpaths(vty, bgp, afi, safi);
bgp_config_write_table_map(vty, bgp, afi, safi);
if (safi == SAFI_EVPN)
bgp_config_write_evpn_info(vty, bgp, afi, safi, &write);
bgp_config_write_evpn_info(vty, bgp, afi, safi);
if (write)
vty_out(vty, " exit-address-family\n");
return write;
vty_endframe(vty, " exit-address-family\n");
}
int bgp_config_write(struct vty *vty)
@ -7119,11 +7039,11 @@ int bgp_config_write(struct vty *vty)
vty_out(vty, "bgp route-map delay-timer %u\n",
bm->rmap_update_timer);
if (write)
vty_out(vty, "!\n");
/* BGP configuration. */
for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
if (write)
vty_out(vty, "!\n");
/* Router bgp ASN */
vty_out(vty, "router bgp %u", bgp->as);
@ -7343,54 +7263,46 @@ int bgp_config_write(struct vty *vty)
vty_out(vty, " no auto-summary\n");
/* IPv4 unicast configuration. */
write +=
bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST);
bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST);
/* IPv4 multicast configuration. */
write += bgp_config_write_family(vty, bgp, AFI_IP,
SAFI_MULTICAST);
bgp_config_write_family(vty, bgp, AFI_IP, SAFI_MULTICAST);
/* IPv4 labeled-unicast configuration. */
write += bgp_config_write_family(vty, bgp, AFI_IP,
SAFI_LABELED_UNICAST);
bgp_config_write_family(vty, bgp, AFI_IP, SAFI_LABELED_UNICAST);
/* IPv4 VPN configuration. */
write += bgp_config_write_family(vty, bgp, AFI_IP,
SAFI_MPLS_VPN);
bgp_config_write_family(vty, bgp, AFI_IP, SAFI_MPLS_VPN);
/* ENCAPv4 configuration. */
write += bgp_config_write_family(vty, bgp, AFI_IP, SAFI_ENCAP);
bgp_config_write_family(vty, bgp, AFI_IP, SAFI_ENCAP);
/* IPv6 unicast configuration. */
write += bgp_config_write_family(vty, bgp, AFI_IP6,
SAFI_UNICAST);
bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_UNICAST);
/* IPv6 multicast configuration. */
write += bgp_config_write_family(vty, bgp, AFI_IP6,
SAFI_MULTICAST);
bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_MULTICAST);
/* IPv6 labeled-unicast configuration. */
write += bgp_config_write_family(vty, bgp, AFI_IP6,
SAFI_LABELED_UNICAST);
bgp_config_write_family(vty, bgp, AFI_IP6,
SAFI_LABELED_UNICAST);
/* IPv6 VPN configuration. */
write += bgp_config_write_family(vty, bgp, AFI_IP6,
SAFI_MPLS_VPN);
bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
/* ENCAPv6 configuration. */
write += bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_ENCAP);
bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_ENCAP);
/* EVPN configuration. */
write +=
bgp_config_write_family(vty, bgp, AFI_L2VPN, SAFI_EVPN);
bgp_config_write_family(vty, bgp, AFI_L2VPN, SAFI_EVPN);
#if ENABLE_BGP_VNC
write += bgp_rfapi_cfg_write(vty, bgp);
bgp_rfapi_cfg_write(vty, bgp);
#endif
write++;
vty_out(vty, "!\n");
}
return write;
return 0;
}
void bgp_master_init(struct thread_master *master)

View File

@ -1238,7 +1238,6 @@ extern void peer_xfer_config(struct peer *dst, struct peer *src);
extern char *peer_uptime(time_t, char *, size_t, u_char, json_object *);
extern int bgp_config_write(struct vty *);
extern void bgp_config_write_family_header(struct vty *, afi_t, safi_t, int *);
extern void bgp_master_init(struct thread_master *master);

View File

@ -1837,6 +1837,7 @@ AC_CONFIG_FILES([Makefile
doc/watchfrr.8
doc/zebra.8
doc/frr.1
doc/frr-args.8
pkgsrc/bgpd.sh pkgsrc/ospf6d.sh pkgsrc/ospfd.sh
pkgsrc/ripd.sh pkgsrc/ripngd.sh pkgsrc/zebra.sh
pkgsrc/eigrpd.sh])

1
debian/frr.install vendored
View File

@ -16,6 +16,7 @@ usr/share/man/man8/ripngd.8
usr/share/man/man8/zebra.8
usr/share/man/man8/isisd.8
usr/share/man/man8/watchfrr.8
usr/share/man/man8/frr-args.8
usr/share/snmp/mibs/
tools/etc/* etc/
tools/*.service lib/systemd/system

View File

@ -79,7 +79,7 @@ frr_TEXINFOS = appendix.texi basic.texi bgpd.texi isisd.texi filter.texi \
.dia.png:
$(DIATOPNG) "$@" $<
man_MANS = frr.1
man_MANS = frr.1 frr-args.8
if PIMD
man_MANS += pimd.8

248
doc/frr-args.8.in Normal file
View 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/

View File

@ -93,7 +93,7 @@ static int config_write_interfaces(struct vty *vty, struct eigrp *eigrp)
struct listnode *node;
for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) {
vty_out(vty, "interface %s\n", ei->ifp->name);
vty_frame(vty, "interface %s\n", ei->ifp->name);
if ((IF_DEF_PARAMS(ei->ifp)->auth_type)
== EIGRP_AUTH_TYPE_MD5) {
@ -128,7 +128,7 @@ static int config_write_interfaces(struct vty *vty, struct eigrp *eigrp)
}
/*Separate this EIGRP interface configuration from the others*/
vty_out(vty, "!\n");
vty_endframe(vty, "!\n");
}
return 0;
@ -140,7 +140,7 @@ static int eigrp_write_interface(struct vty *vty)
struct interface *ifp;
for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
vty_out(vty, "interface %s\n", ifp->name);
vty_frame(vty, "interface %s\n", ifp->name);
if (ifp->desc)
vty_out(vty, " description %s\n", ifp->desc);
@ -157,7 +157,7 @@ static int eigrp_write_interface(struct vty *vty)
vty_out(vty, " ip hold-time eigrp %u\n",
IF_DEF_PARAMS(ifp)->v_wait);
vty_out(vty, "!\n");
vty_endframe(vty, "!\n");
}
return 0;

View File

@ -948,7 +948,7 @@ int isis_interface_config_write(struct vty *vty)
continue;
/* IF name */
vty_out(vty, "interface %s\n", ifp->name);
vty_frame(vty, "interface %s\n", ifp->name);
write++;
/* IF desc */
if (ifp->desc) {
@ -1145,7 +1145,7 @@ int isis_interface_config_write(struct vty *vty)
}
write += circuit_write_mt_settings(circuit, vty);
}
vty_out(vty, "!\n");
vty_endframe(vty, "!\n");
}
return write;

View File

@ -101,13 +101,15 @@ static const struct optspec os_always = {
static const struct option lo_cfg_pid_dry[] = {
{"pid_file", required_argument, NULL, 'i'},
{"config_file", required_argument, NULL, 'f'},
{"pathspace", required_argument, NULL, 'N'},
{"dryrun", no_argument, NULL, 'C'},
{"terminal", no_argument, NULL, 't'},
{NULL}};
static const struct optspec os_cfg_pid_dry = {
"f:i:Ct",
"f:i:CtN:",
" -f, --config_file Set configuration file name\n"
" -i, --pid_file Set process identifier file name\n"
" -N, --pathspace Insert prefix into config & socket paths\n"
" -C, --dryrun Check configuration for validity and exit\n"
" -t, --terminal Open terminal session on stdio\n"
" -d -t Daemonize after terminal session ends\n",
@ -351,6 +353,23 @@ static int frr_opt(int opt)
return 1;
di->config_file = optarg;
break;
case 'N':
if (di->flags & FRR_NO_CFG_PID_DRY)
return 1;
if (di->pathspace) {
fprintf(stderr,
"-N/--pathspace option specified more than once!\n");
errors++;
break;
}
if (strchr(optarg, '/') || strchr(optarg, '.')) {
fprintf(stderr,
"slashes or dots are not permitted in the --pathspace option.\n");
errors++;
break;
}
di->pathspace = optarg;
break;
case 'C':
if (di->flags & FRR_NO_CFG_PID_DRY)
return 1;
@ -500,14 +519,25 @@ struct thread_master *frr_init(void)
struct option_chain *oc;
struct frrmod_runtime *module;
char moderr[256];
char p_instance[16] = "", p_pathspace[256] = "";
const char *dir;
dir = di->module_path ? di->module_path : frr_moduledir;
srandom(time(NULL));
if (di->instance)
if (di->instance) {
snprintf(frr_protonameinst, sizeof(frr_protonameinst), "%s[%u]",
di->logname, di->instance);
snprintf(p_instance, sizeof(p_instance), "-%d", di->instance);
}
if (di->pathspace)
snprintf(p_pathspace, sizeof(p_pathspace), "/%s",
di->pathspace);
snprintf(config_default, sizeof(config_default), "%s%s/%s%s.conf",
frr_sysconfdir, p_pathspace, di->name, p_instance);
snprintf(pidfile_default, sizeof(pidfile_default), "%s%s/%s%s.pid",
frr_vtydir, p_pathspace, di->name, p_instance);
zprivs_preinit(di->privs);
@ -695,14 +725,6 @@ void frr_config_fork(void)
{
hook_call(frr_late_init, master);
if (di->instance) {
snprintf(config_default, sizeof(config_default),
"%s/%s-%d.conf", frr_sysconfdir, di->name,
di->instance);
snprintf(pidfile_default, sizeof(pidfile_default),
"%s/%s-%d.pid", frr_vtydir, di->name, di->instance);
}
vty_read_config(di->config_file, config_default);
/* Don't start execution if we are in dry-run mode */
@ -723,7 +745,13 @@ void frr_vty_serv(void)
* (not currently set anywhere) */
if (!di->vty_path) {
const char *dir;
dir = di->vty_sock_path ? di->vty_sock_path : frr_vtydir;
char defvtydir[256];
snprintf(defvtydir, sizeof(defvtydir), "%s%s%s", frr_vtydir,
di->pathspace ? "/" : "",
di->pathspace ? di->pathspace : "");
dir = di->vty_sock_path ? di->vty_sock_path : defvtydir;
if (di->instance)
snprintf(vtypath_default, sizeof(vtypath_default),

View File

@ -54,6 +54,7 @@ struct frr_daemon_info {
const char *pid_file;
const char *vty_path;
const char *module_path;
const char *pathspace;
const char *proghelp;
void (*printhelp)(FILE *target);

View File

@ -91,6 +91,25 @@ char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG;
static int do_log_commands = 0;
void vty_frame(struct vty *vty, const char *format, ...)
{
va_list args;
va_start(args, format);
vsnprintf(vty->frame + vty->frame_pos,
sizeof(vty->frame) - vty->frame_pos,
format, args);
vty->frame_pos = strlen(vty->frame);
va_end(args);
}
void vty_endframe(struct vty *vty, const char *endtext)
{
if (vty->frame_pos == 0 && endtext)
vty_out(vty, "%s", endtext);
vty->frame_pos = 0;
}
/* VTY standard output function. */
int vty_out(struct vty *vty, const char *format, ...)
{
@ -100,6 +119,11 @@ int vty_out(struct vty *vty, const char *format, ...)
char buf[1024];
char *p = NULL;
if (vty->frame_pos) {
vty->frame_pos = 0;
vty_out(vty, "%s", vty->frame);
}
if (vty_shell(vty)) {
va_start(args, format);
vprintf(format, args);

View File

@ -125,6 +125,12 @@ struct vty {
/* What address is this vty comming from. */
char address[SU_ADDRSTRLEN];
/* "frame" output. This is buffered and will be printed if some
* actual output follows, or will be discarded if the frame ends
* without any output. */
size_t frame_pos;
char frame[1024];
};
static inline void vty_push_context(struct vty *vty, int node, uint64_t id)
@ -247,7 +253,16 @@ extern void vty_terminate(void);
extern void vty_reset(void);
extern struct vty *vty_new(void);
extern struct vty *vty_stdio(void (*atclose)(int isexit));
/* - vty_frame() output goes to a buffer (for context-begin markers)
* - vty_out() will first print this buffer, and clear it
* - vty_endframe() clears the buffer without printing it, and prints an
* extra string if the buffer was empty before (for context-end markers)
*/
extern int vty_out(struct vty *, const char *, ...) PRINTF_ATTRIBUTE(2, 3);
extern void vty_frame(struct vty *, const char *, ...) PRINTF_ATTRIBUTE(2, 3);
extern void vty_endframe(struct vty *, const char *);
extern void vty_read_config(const char *, char *);
extern void vty_time_print(struct vty *, int);
extern void vty_serv_sock(const char *, unsigned short, const char *);

View File

@ -854,7 +854,7 @@ static int interface_config_write(struct vty *vty)
int i;
for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
vty_out (vty, "interface %s\n", ifp->name);
vty_frame(vty, "interface %s\n", ifp->name);
if (ifp->desc)
vty_out (vty, " description %s\n", ifp->desc);
@ -913,7 +913,7 @@ static int interface_config_write(struct vty *vty)
}
}
vty_out (vty, "!\n");
vty_endframe(vty, "!\n");
}
return 0;

View File

@ -1755,7 +1755,7 @@ static int config_write_ospf6_interface(struct vty *vty)
if (oi == NULL)
continue;
vty_out(vty, "interface %s\n", oi->interface->name);
vty_frame(vty, "interface %s\n", oi->interface->name);
if (ifp->desc)
vty_out(vty, " description %s\n", ifp->desc);
@ -1808,7 +1808,7 @@ static int config_write_ospf6_interface(struct vty *vty)
ospf6_bfd_write_config(vty, oi);
vty_out(vty, "!\n");
vty_endframe(vty, "!\n");
}
return 0;
}

View File

@ -8156,8 +8156,8 @@ static int config_write_interface(struct vty *vty)
if (ifp->ifindex == IFINDEX_DELETED)
continue;
vty_out(vty, "!\n");
vty_out(vty, "interface %s\n", ifp->name);
vty_frame(vty, "!\n");
vty_frame(vty, "interface %s\n", ifp->name);
if (ifp->desc)
vty_out(vty, " description %s\n", ifp->desc);
@ -8371,6 +8371,8 @@ static int config_write_interface(struct vty *vty)
} while (rn);
ospf_opaque_config_write_if(vty, ifp);
vty_endframe(vty, NULL);
}
return write;

View File

@ -255,7 +255,7 @@ int pim_interface_config_write(struct vty *vty)
/* IF name */
if (vrf->vrf_id == VRF_DEFAULT)
vty_out(vty, "interface %s\n", ifp->name);
vty_frame(vty, "interface %s\n", ifp->name);
else
vty_out(vty, "interface %s vrf %s\n", ifp->name,
vrf->name);
@ -363,7 +363,7 @@ int pim_interface_config_write(struct vty *vty)
pim_static_write_mroute(pim, vty, ifp);
pim_bfd_write_config(vty, ifp);
}
vty_out(vty, "!\n");
vty_endframe(vty, "!\n");
++writes;
}
}

View File

@ -1751,7 +1751,7 @@ static int rip_interface_config_write(struct vty *vty)
&& (!ri->auth_str) && (!ri->key_chain))
continue;
vty_out(vty, "interface %s\n", ifp->name);
vty_frame(vty, "interface %s\n", ifp->name);
if (ifp->desc)
vty_out(vty, " description %s\n", ifp->desc);
@ -1807,7 +1807,7 @@ static int rip_interface_config_write(struct vty *vty)
vty_out(vty, " ip rip authentication key-chain %s\n",
ri->key_chain);
vty_out(vty, "!\n");
vty_endframe(vty, "!\n");
}
return 0;
}

View File

@ -1084,7 +1084,7 @@ static int interface_config_write(struct vty *vty)
&& (ri->split_horizon == ri->split_horizon_default))
continue;
vty_out(vty, "interface %s\n", ifp->name);
vty_frame(vty, "interface %s\n", ifp->name);
if (ifp->desc)
vty_out(vty, " description %s\n", ifp->desc);
@ -1105,7 +1105,7 @@ static int interface_config_write(struct vty *vty)
}
}
vty_out(vty, "!\n");
vty_endframe(vty, "!\n");
write++;
}

View File

@ -2295,12 +2295,12 @@ int vtysh_write_config_integrated(void)
fprintf(stdout, "Building Configuration...\n");
backup_config_file(quagga_config);
fp = fopen(quagga_config, "w");
backup_config_file(frr_config);
fp = fopen(frr_config, "w");
if (fp == NULL) {
fprintf(stdout,
"%% Error: failed to open configuration file %s: %s\n",
quagga_config, safe_strerror(errno));
frr_config, safe_strerror(errno));
return CMD_WARNING_CONFIG_FAILED;
}
fd = fileno(fp);
@ -2313,7 +2313,7 @@ int vtysh_write_config_integrated(void)
if (fchmod(fd, CONFIGFILE_MASK) != 0) {
printf("%% Warning: can't chmod configuration file %s: %s\n",
quagga_config, safe_strerror(errno));
frr_config, safe_strerror(errno));
err++;
}
@ -2345,18 +2345,18 @@ int vtysh_write_config_integrated(void)
if ((uid != (uid_t)-1 || gid != (gid_t)-1)
&& fchown(fd, uid, gid)) {
printf("%% Warning: can't chown configuration file %s: %s\n",
quagga_config, safe_strerror(errno));
frr_config, safe_strerror(errno));
err++;
}
} else {
printf("%% Warning: stat() failed on %s: %s\n", quagga_config,
printf("%% Warning: stat() failed on %s: %s\n", frr_config,
safe_strerror(errno));
err++;
}
fclose(fp);
printf("Integrated configuration saved to %s\n", quagga_config);
printf("Integrated configuration saved to %s\n", frr_config);
if (err)
return CMD_WARNING;
@ -2370,7 +2370,7 @@ static bool want_config_integrated(void)
switch (vtysh_write_integrated) {
case WRITE_INTEGRATED_UNSPECIFIED:
if (stat(quagga_config, &s) && errno == ENOENT)
if (stat(frr_config, &s) && errno == ENOENT)
return false;
return true;
case WRITE_INTEGRATED_NO:
@ -2712,7 +2712,7 @@ static int vtysh_connect(struct vtysh_client *vclient)
if (!vclient->path[0])
snprintf(vclient->path, sizeof(vclient->path), "%s/%s.vty",
vty_sock_path, vclient->name);
vtydir, vclient->name);
path = vclient->path;
/* Stat socket to see if we have permission to access it. */
@ -2806,7 +2806,7 @@ static void vtysh_update_all_insances(struct vtysh_client *head_client)
return;
/* ls vty_sock_dir and look for all files ending in .vty */
dir = opendir(vty_sock_path);
dir = opendir(vtydir);
if (dir) {
while ((file = readdir(dir)) != NULL) {
if (begins_with(file->d_name, "ospfd-")
@ -2814,7 +2814,7 @@ static void vtysh_update_all_insances(struct vtysh_client *head_client)
if (n == MAXIMUM_INSTANCES) {
fprintf(stderr,
"Parsing %s, client limit(%d) reached!\n",
vty_sock_path, n);
vtydir, n);
break;
}
client = (struct vtysh_client *)malloc(
@ -2823,7 +2823,7 @@ static void vtysh_update_all_insances(struct vtysh_client *head_client)
client->name = "ospfd";
client->flag = VTYSH_OSPFD;
snprintf(client->path, sizeof(client->path),
"%s/%s", vty_sock_path, file->d_name);
"%s/%s", vtydir, file->d_name);
client->next = NULL;
vtysh_client_sorted_insert(head_client, client);
n++;

View File

@ -49,10 +49,6 @@ DECLARE_MGROUP(MVTYSH)
#define VTYSH_NS VTYSH_ZEBRA
#define VTYSH_VRF VTYSH_ZEBRA|VTYSH_PIMD
/* vtysh local configuration file. */
#define VTYSH_DEFAULT_CONFIG "vtysh.conf"
#define FRR_DEFAULT_CONFIG "frr.conf"
enum vtysh_write_integrated {
WRITE_INTEGRATED_UNSPECIFIED,
WRITE_INTEGRATED_NO,
@ -61,7 +57,8 @@ enum vtysh_write_integrated {
extern enum vtysh_write_integrated vtysh_write_integrated;
extern char *quagga_config;
extern char frr_config[];
extern char vtydir[];
void vtysh_init_vty(void);
void vtysh_init_cmd(void);
@ -93,11 +90,12 @@ void vtysh_config_init(void);
void vtysh_pager_init(void);
void suid_on(void);
void suid_off(void);
/* Child process execution flag. */
extern int execute_flag;
extern struct vty *vty;
extern const char *vty_sock_path;
#endif /* VTYSH_H */

View File

@ -44,18 +44,22 @@
/* VTY shell program name. */
char *progname;
/* SUID mode */
static uid_t elevuid, realuid;
static gid_t elevgid, realgid;
#define VTYSH_CONFIG_NAME "vtysh.conf"
#define FRR_CONFIG_NAME "frr.conf"
/* Configuration file name and directory. */
static char vtysh_config_always[MAXPATHLEN] = SYSCONFDIR VTYSH_DEFAULT_CONFIG;
static char quagga_config_default[MAXPATHLEN] = SYSCONFDIR FRR_DEFAULT_CONFIG;
char *quagga_config = quagga_config_default;
char history_file[MAXPATHLEN];
static char vtysh_config[MAXPATHLEN];
char frr_config[MAXPATHLEN];
char vtydir[MAXPATHLEN];
static char history_file[MAXPATHLEN];
/* Flag for indicate executing child command. */
int execute_flag = 0;
/* VTY Socket prefix */
const char *vty_sock_path = NULL;
/* For sigsetjmp() & siglongjmp(). */
static sigjmp_buf jmpbuf;
@ -145,6 +149,7 @@ static void usage(int status)
"-m, --markfile Mark input file with context end\n"
" --vty_socket Override vty socket path\n"
" --config_dir Override config directory path\n"
"-N --pathspace Insert prefix into config & socket paths\n"
"-w, --writeconfig Write integrated config (frr.conf) and exit\n"
"-h, --help Display this help and exit\n\n"
"Note that multiple commands may be executed from the command\n"
@ -174,6 +179,7 @@ struct option longopts[] = {
{"noerror", no_argument, NULL, 'n'},
{"mark", no_argument, NULL, 'm'},
{"writeconfig", no_argument, NULL, 'w'},
{"pathspace", no_argument, NULL, 'N'},
{0}};
/* Read a string, and return a pointer to it. Returns NULL on EOF. */
@ -249,6 +255,30 @@ static void vtysh_unflock_config(void)
close(flock_fd);
}
void suid_on(void)
{
if (elevuid != realuid && seteuid(elevuid)) {
perror("seteuid(on)");
exit(1);
}
if (elevgid != realgid && setegid(elevgid)) {
perror("setegid(on)");
exit(1);
}
}
void suid_off(void)
{
if (elevuid != realuid && seteuid(realuid)) {
perror("seteuid(off)");
exit(1);
}
if (elevgid != realgid && setegid(realgid)) {
perror("setegid(off)");
exit(1);
}
}
/* VTY shell main routine. */
int main(int argc, char **argv, char **env)
{
@ -258,7 +288,6 @@ int main(int argc, char **argv, char **env)
int boot_flag = 0;
const char *daemon_name = NULL;
const char *inputfile = NULL;
const char *vtysh_configfile_name;
struct cmd_rec {
char *line;
struct cmd_rec *next;
@ -270,16 +299,22 @@ int main(int argc, char **argv, char **env)
int writeconfig = 0;
int ret = 0;
char *homedir = NULL;
int ditch_suid = 0;
char sysconfdir[MAXPATHLEN];
char pathspace[MAXPATHLEN] = "";
/* check for restricted functionality if vtysh is run setuid */
int restricted = (getuid() != geteuid()) || (getgid() != getegid());
/* SUID: drop down to calling user & go back up when needed */
elevuid = geteuid();
elevgid = getegid();
realuid = getuid();
realgid = getgid();
suid_off();
/* Preserve name of myself. */
progname = ((p = strrchr(argv[0], '/')) ? ++p : argv[0]);
/* if logging open now */
if ((p = getenv("VTYSH_LOG")) != NULL)
logfile = fopen(p, "a");
strlcpy(sysconfdir, frr_sysconfdir, sizeof(sysconfdir));
strlcpy(vtydir, frr_vtydir, sizeof(vtydir));
/* Option handling. */
while (1) {
@ -307,63 +342,20 @@ int main(int argc, char **argv, char **env)
tail = cr;
} break;
case OPTION_VTYSOCK:
vty_sock_path = optarg;
ditch_suid = 1; /* option disables SUID */
strlcpy(vtydir, optarg, sizeof(vtydir));
break;
case OPTION_CONFDIR:
/*
* Skip option for Config Directory if setuid
*/
if (restricted) {
ditch_suid = 1; /* option disables SUID */
strlcpy(sysconfdir, optarg, sizeof(sysconfdir));
break;
case 'N':
if (strchr(optarg, '/') || strchr(optarg, '.')) {
fprintf(stderr,
"Overriding of Config Directory blocked for vtysh with setuid");
return 1;
"slashes or dots are not permitted in the --pathspace option.\n");
exit(1);
}
/*
* Overwrite location for vtysh.conf
*/
vtysh_configfile_name =
strrchr(VTYSH_DEFAULT_CONFIG, '/');
if (vtysh_configfile_name)
/* skip '/' */
vtysh_configfile_name++;
else
/*
* VTYSH_DEFAULT_CONFIG configured with relative
* path
* during config? Should really never happen for
* sensible config
*/
vtysh_configfile_name =
(char *)VTYSH_DEFAULT_CONFIG;
strlcpy(vtysh_config_always, optarg,
sizeof(vtysh_config_always));
strlcat(vtysh_config_always, "/",
sizeof(vtysh_config_always));
strlcat(vtysh_config_always, vtysh_configfile_name,
sizeof(vtysh_config_always));
/*
* Overwrite location for frr.conf
*/
vtysh_configfile_name =
strrchr(FRR_DEFAULT_CONFIG, '/');
if (vtysh_configfile_name)
/* skip '/' */
vtysh_configfile_name++;
else
/*
* FRR_DEFAULT_CONFIG configured with relative
* path
* during config? Should really never happen for
* sensible config
*/
vtysh_configfile_name =
(char *)FRR_DEFAULT_CONFIG;
strlcpy(quagga_config_default, optarg,
sizeof(vtysh_config_always));
strlcat(quagga_config_default, "/",
sizeof(vtysh_config_always));
strlcat(quagga_config_default, vtysh_configfile_name,
sizeof(quagga_config_default));
snprintf(pathspace, sizeof(pathspace), "/%s", optarg);
break;
case 'd':
daemon_name = optarg;
@ -395,8 +387,10 @@ int main(int argc, char **argv, char **env)
}
}
if (!vty_sock_path)
vty_sock_path = frr_vtydir;
if (ditch_suid) {
elevuid = realuid;
elevgid = realgid;
}
if (markfile + writeconfig + dryrun + boot_flag > 1) {
fprintf(stderr,
@ -410,6 +404,12 @@ int main(int argc, char **argv, char **env)
"NOT SUPPORTED since its\nresults are inconsistent!\n");
}
snprintf(vtysh_config, sizeof(vtysh_config), "%s%s/%s",
sysconfdir, pathspace, VTYSH_CONFIG_NAME);
snprintf(frr_config, sizeof(frr_config), "%s%s/%s",
sysconfdir, pathspace, FRR_CONFIG_NAME);
strlcat(vtydir, pathspace, sizeof(vtydir));
/* Initialize user input buffer. */
line_read = NULL;
setlinebuf(stdout);
@ -425,8 +425,11 @@ int main(int argc, char **argv, char **env)
vty_init_vtysh();
/* Read vtysh configuration file before connecting to daemons. */
vtysh_read_config(vtysh_config_always);
/* Read vtysh configuration file before connecting to daemons.
* (file may not be readable to calling user in SUID mode) */
suid_on();
vtysh_read_config(vtysh_config);
suid_off();
if (markfile) {
if (!inputfile) {
@ -442,7 +445,7 @@ int main(int argc, char **argv, char **env)
if (inputfile) {
ret = vtysh_read_config(inputfile);
} else {
ret = vtysh_read_config(quagga_config_default);
ret = vtysh_read_config(frr_config);
}
exit(ret);
@ -486,6 +489,9 @@ int main(int argc, char **argv, char **env)
}
}
/* SUID: go back up elevated privs */
suid_on();
/* Make sure we pass authentication before proceeding. */
vtysh_auth();
@ -498,6 +504,9 @@ int main(int argc, char **argv, char **env)
exit(1);
}
/* SUID: back down, don't need privs further on */
suid_off();
if (writeconfig) {
vtysh_execute("enable");
return vtysh_write_config_integrated();
@ -531,6 +540,17 @@ int main(int argc, char **argv, char **env)
}
}
if (getenv("VTYSH_LOG")) {
const char *logpath = getenv("VTYSH_LOG");
logfile = fopen(logpath, "a");
if (!logfile) {
fprintf(stderr, "Failed to open logfile (%s): %s\n",
logpath, strerror(errno));
exit(1);
}
}
/* If eval mode. */
if (cmd) {
/* Enter into enable node. */
@ -592,13 +612,13 @@ int main(int argc, char **argv, char **env)
/* Boot startup configuration file. */
if (boot_flag) {
vtysh_flock_config(quagga_config);
int ret = vtysh_read_config(quagga_config);
vtysh_flock_config(frr_config);
int ret = vtysh_read_config(frr_config);
vtysh_unflock_config();
if (ret) {
fprintf(stderr,
"Configuration file[%s] processing failure: %d\n",
quagga_config, ret);
frr_config, ret);
if (no_error)
exit(0);
else

View File

@ -2793,7 +2793,7 @@ static int if_config_write(struct vty *vty)
vrf = vrf_lookup_by_id(ifp->vrf_id);
if (ifp->vrf_id == VRF_DEFAULT)
vty_out(vty, "interface %s\n", ifp->name);
vty_frame(vty, "interface %s\n", ifp->name);
else
vty_out(vty, "interface %s vrf %s\n", ifp->name,
vrf->name);
@ -2844,7 +2844,7 @@ static int if_config_write(struct vty *vty)
link_params_config_write(vty, ifp);
vty_out(vty, "!\n");
vty_endframe(vty, "!\n");
}
return 0;
}