summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@diac24.net>2019-05-15 21:32:50 +0200
committerDavid Lamparter <equinox@diac24.net>2019-05-15 21:32:50 +0200
commitcd4f050587c444509ec286247f95606fe6f7f756 (patch)
treedb21369925a50a674b5fa2426737c45209a031d5
parent0189e6d73cdbabf2b320b40248d75db1791d7424 (diff)
parent33e56da60666cd26ca18787104e721b9df9ed4a2 (diff)
Merge tag 'frr-6.0.3' into debian/master
FRRouting Release 6.0.3
-rw-r--r--Makefile.am3
-rw-r--r--bfdd/bfd.c8
-rw-r--r--bgpd/bgp_aspath.c55
-rw-r--r--bgpd/bgp_attr.c28
-rw-r--r--bgpd/bgp_evpn.c18
-rw-r--r--bgpd/bgp_flowspec.c14
-rw-r--r--bgpd/bgp_label.c12
-rw-r--r--bgpd/bgp_mplsvpn.c12
-rw-r--r--bgpd/bgp_packet.c7
-rw-r--r--bgpd/bgp_route.c32
-rw-r--r--bgpd/bgp_route.h18
-rw-r--r--bgpd/bgp_rpki.c22
-rw-r--r--bgpd/bgp_vty.c103
-rw-r--r--bgpd/bgpd.c9
-rw-r--r--bgpd/bgpd.h6
-rw-r--r--changelog-auto.in23
-rwxr-xr-xconfigure.ac3
-rw-r--r--doc/developer/_static/overrides.css233
-rw-r--r--doc/developer/conf.py13
-rw-r--r--doc/manpages/watchfrr.rst29
-rw-r--r--doc/user/_static/overrides.css240
-rw-r--r--doc/user/conf.py13
-rw-r--r--doc/user/setup.rst31
-rw-r--r--doc/user/vtysh.rst31
-rw-r--r--include/linux/if_addr.h69
-rw-r--r--include/subdir.am1
-rw-r--r--ldpd/labelmapping.c4
-rw-r--r--ldpd/ldpe.c18
-rw-r--r--ldpd/socket.c13
-rw-r--r--lib/command.c2
-rw-r--r--lib/if.h9
-rw-r--r--lib/log.c8
-rw-r--r--lib/log.h6
-rw-r--r--nhrpd/nhrp_interface.c6
-rw-r--r--ospfd/ospf_interface.c17
-rw-r--r--ospfd/ospf_interface.h1
-rw-r--r--ospfd/ospf_vty.c44
-rw-r--r--ospfd/ospfd.c1
-rw-r--r--pimd/pim_zebra.c2
-rw-r--r--redhat/daemons84
-rwxr-xr-xredhat/frr.init577
-rw-r--r--redhat/frr.service23
-rw-r--r--redhat/frr.spec.in34
-rw-r--r--tools/etc/frr/daemons2
-rw-r--r--tools/frr.service6
-rw-r--r--tools/frrcommon.sh.in22
-rw-r--r--tools/frrinit.sh.in2
-rwxr-xr-xtools/tarsource.sh2
-rw-r--r--tools/watchfrr.sh.in2
-rw-r--r--vtysh/vtysh.c14
-rw-r--r--watchfrr/watchfrr.c14
-rw-r--r--zebra/connected.c13
-rw-r--r--zebra/connected.h6
-rw-r--r--zebra/if_ioctl.c5
-rw-r--r--zebra/if_ioctl_solaris.c5
-rw-r--r--zebra/if_netlink.c10
-rw-r--r--zebra/kernel_socket.c8
-rw-r--r--zebra/label_manager.c8
-rw-r--r--zebra/zebra_ns.c1
-rw-r--r--zebra/zebra_pw.c1
-rw-r--r--zebra/zebra_rib.c2
-rw-r--r--zebra/zebra_vty.c24
62 files changed, 1107 insertions, 922 deletions
diff --git a/Makefile.am b/Makefile.am
index 5be32649fa..bcf6ac0edc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -165,9 +165,6 @@ EXTRA_DIST += \
python/clidef.py \
python/clippy/__init__.py \
\
- redhat/frr.init \
- redhat/frr.service \
- redhat/daemons \
redhat/frr.logrotate \
redhat/frr.pam \
redhat/frr.spec \
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index 66c781c290..d6e0230d2d 100644
--- a/bfdd/bfd.c
+++ b/bfdd/bfd.c
@@ -817,10 +817,10 @@ void integer2timestr(uint64_t time, char *buf, size_t buflen)
int rv;
#define MINUTES (60)
-#define HOURS (24 * MINUTES)
-#define DAYS (30 * HOURS)
-#define MONTHS (12 * DAYS)
-#define YEARS (MONTHS)
+#define HOURS (60 * MINUTES)
+#define DAYS (24 * HOURS)
+#define MONTHS (30 * DAYS)
+#define YEARS (12 * MONTHS)
if (time >= YEARS) {
year = time / YEARS;
time -= year * YEARS;
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index b532927e80..49e43c39e2 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -1380,39 +1380,45 @@ static struct aspath *aspath_merge(struct aspath *as1, struct aspath *as2)
/* Prepend as1 to as2. as2 should be uninterned aspath. */
struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2)
{
- struct assegment *seg1;
- struct assegment *seg2;
+ struct assegment *as1segtail;
+ struct assegment *as2segtail;
+ struct assegment *as2seghead;
if (!as1 || !as2)
return NULL;
- seg1 = as1->segments;
- seg2 = as2->segments;
-
/* If as2 is empty, only need to dupe as1's chain onto as2 */
- if (seg2 == NULL) {
+ if (as2->segments == NULL) {
as2->segments = assegment_dup_all(as1->segments);
aspath_str_update(as2, false);
return as2;
}
/* If as1 is empty AS, no prepending to do. */
- if (seg1 == NULL)
+ if (as1->segments == NULL)
return as2;
/* find the tail as1's segment chain. */
- while (seg1 && seg1->next)
- seg1 = seg1->next;
+ as1segtail = as1->segments;
+ while (as1segtail && as1segtail->next)
+ as1segtail = as1segtail->next;
/* Delete any AS_CONFED_SEQUENCE segment from as2. */
- if (seg1->type == AS_SEQUENCE && seg2->type == AS_CONFED_SEQUENCE)
+ if (as1segtail->type == AS_SEQUENCE
+ && as2->segments->type == AS_CONFED_SEQUENCE)
as2 = aspath_delete_confed_seq(as2);
+ if (!as2->segments) {
+ as2->segments = assegment_dup_all(as1->segments);
+ aspath_str_update(as2, false);
+ return as2;
+ }
+
/* Compare last segment type of as1 and first segment type of as2. */
- if (seg1->type != seg2->type)
+ if (as1segtail->type != as2->segments->type)
return aspath_merge(as1, as2);
- if (seg1->type == AS_SEQUENCE) {
+ if (as1segtail->type == AS_SEQUENCE) {
/* We have two chains of segments, as1->segments and seg2,
* and we have to attach them together, merging the attaching
* segments together into one.
@@ -1422,23 +1428,28 @@ struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2)
* 3. attach chain after seg2
*/
+ /* save as2 head */
+ as2seghead = as2->segments;
+
/* dupe as1 onto as2's head */
- seg1 = as2->segments = assegment_dup_all(as1->segments);
+ as2segtail = as2->segments = assegment_dup_all(as1->segments);
- /* refind the tail of as2, reusing seg1 */
- while (seg1 && seg1->next)
- seg1 = seg1->next;
+ /* refind the tail of as2 */
+ while (as2segtail && as2segtail->next)
+ as2segtail = as2segtail->next;
/* merge the old head, seg2, into tail, seg1 */
- seg1 = assegment_append_asns(seg1, seg2->as, seg2->length);
+ assegment_append_asns(as2segtail, as2seghead->as,
+ as2seghead->length);
- /* bypass the merged seg2, and attach any chain after it to
- * chain descending from as2's head
+ /*
+ * bypass the merged seg2, and attach any chain after it
+ * to chain descending from as2's head
*/
- seg1->next = seg2->next;
+ as2segtail->next = as2seghead->next;
- /* seg2 is now referenceless and useless*/
- assegment_free(seg2);
+ /* as2->segments is now referenceless and useless */
+ assegment_free(as2seghead);
/* we've now prepended as1's segment chain to as2, merging
* the inbetween AS_SEQUENCE of seg2 in the process
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 640c3bdb7a..a8eab9cfec 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -3001,6 +3001,22 @@ void bgp_packet_mpattr_end(struct stream *s, size_t sizep)
stream_putw_at(s, sizep, (stream_get_endp(s) - sizep) - 2);
}
+static int bgp_append_local_as(struct peer *peer, afi_t afi, safi_t safi)
+{
+ if (!BGP_AS_IS_PRIVATE(peer->local_as)
+ || (BGP_AS_IS_PRIVATE(peer->local_as)
+ && !CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_REMOVE_PRIVATE_AS)
+ && !CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
+ && !CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
+ && !CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)))
+ return 1;
+ return 0;
+}
+
/* Make attribute packet. */
bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
struct stream *s, struct attr *attr,
@@ -3066,12 +3082,12 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
/* If replace-as is specified, we only use the
change_local_as when
advertising routes. */
- if (!CHECK_FLAG(
- peer->flags,
- PEER_FLAG_LOCAL_AS_REPLACE_AS)) {
- aspath = aspath_add_seq(aspath,
- peer->local_as);
- }
+ if (!CHECK_FLAG(peer->flags,
+ PEER_FLAG_LOCAL_AS_REPLACE_AS))
+ if (bgp_append_local_as(peer, afi,
+ safi))
+ aspath = aspath_add_seq(
+ aspath, peer->local_as);
aspath = aspath_add_seq(aspath,
peer->change_local_as);
} else {
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 7ee920aba8..4810b73bc7 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -4694,7 +4694,7 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
if (addpath_encoded) {
/* When packet overflow occurs return immediately. */
if (pnt + BGP_ADDPATH_ID_LEN > lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
addpath_id = ntohl(*((uint32_t *)pnt));
pnt += BGP_ADDPATH_ID_LEN;
@@ -4702,14 +4702,14 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
/* All EVPN NLRI types start with type and length. */
if (pnt + 2 > lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_EVPN_MISSING_TYPE;
rtype = *pnt++;
psize = *pnt++;
/* When packet overflow occur return immediately. */
if (pnt + psize > lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
switch (rtype) {
case BGP_EVPN_MAC_IP_ROUTE:
@@ -4720,7 +4720,7 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
BGP_ERR_EVPN_FAIL,
"%u:%s - Error in processing EVPN type-2 NLRI size %d",
peer->bgp->vrf_id, peer->host, psize);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_EVPN_TYPE2_SIZE;
}
break;
@@ -4732,7 +4732,7 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
BGP_ERR_PKT_PROCESS,
"%u:%s - Error in processing EVPN type-3 NLRI size %d",
peer->bgp->vrf_id, peer->host, psize);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_EVPN_TYPE3_SIZE;
}
break;
@@ -4744,7 +4744,7 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
BGP_ERR_PKT_PROCESS,
"%u:%s - Error in processing EVPN type-4 NLRI size %d",
peer->bgp->vrf_id, peer->host, psize);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_EVPN_TYPE4_SIZE;
}
break;
@@ -4755,7 +4755,7 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
BGP_ERR_PKT_PROCESS,
"%u:%s - Error in processing EVPN type-5 NLRI size %d",
peer->bgp->vrf_id, peer->host, psize);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_EVPN_TYPE5_SIZE;
}
break;
@@ -4766,9 +4766,9 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
/* Packet length consistency check. */
if (pnt != lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
- return 0;
+ return BGP_NLRI_PARSE_OK;
}
/*
diff --git a/bgpd/bgp_flowspec.c b/bgpd/bgp_flowspec.c
index e29508bf36..418ad7c48a 100644
--- a/bgpd/bgp_flowspec.c
+++ b/bgpd/bgp_flowspec.c
@@ -106,14 +106,14 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
if (afi == AFI_IP6) {
flog_err(LIB_ERR_DEVELOPMENT,
"BGP flowspec IPv6 not supported");
- return -1;
+ return BGP_NLRI_PARSE_ERROR_FLOWSPEC_IPV6_NOT_SUPPORTED;
}
if (packet->length >= FLOWSPEC_NLRI_SIZELIMIT) {
flog_err(BGP_ERR_FLOWSPEC_PACKET,
"BGP flowspec nlri length maximum reached (%u)",
packet->length);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_FLOWSPEC_NLRI_SIZELIMIT;
}
for (; pnt < lim; pnt += psize) {
@@ -122,7 +122,7 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
/* All FlowSpec NLRI begin with length. */
if (pnt + 1 > lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
psize = *pnt++;
@@ -131,12 +131,12 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
flog_err(BGP_ERR_FLOWSPEC_PACKET,
"Flowspec NLRI length inconsistent ( size %u seen)",
psize);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
}
if (bgp_fs_nlri_validate(pnt, psize) < 0) {
flog_err(BGP_ERR_FLOWSPEC_PACKET,
"Bad flowspec format or NLRI options not supported");
- return -1;
+ return BGP_NLRI_PARSE_ERROR_FLOWSPEC_BAD_FORMAT;
}
p.family = AF_FLOWSPEC;
p.prefixlen = 0;
@@ -191,8 +191,8 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
flog_err(BGP_ERR_FLOWSPEC_INSTALLATION,
"Flowspec NLRI failed to be %s.",
attr ? "added" : "withdrawn");
- return -1;
+ return BGP_NLRI_PARSE_ERROR;
}
}
- return 0;
+ return BGP_NLRI_PARSE_OK;
}
diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c
index 633e589333..a93cafcb25 100644
--- a/bgpd/bgp_label.c
+++ b/bgpd/bgp_label.c
@@ -232,7 +232,7 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
/* When packet overflow occurs return immediately. */
if (pnt + BGP_ADDPATH_ID_LEN > lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
addpath_id = ntohl(*((uint32_t *)pnt));
pnt += BGP_ADDPATH_ID_LEN;
@@ -249,7 +249,7 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
BGP_ERR_UPDATE_RCV,
"%s [Error] Update packet error / L-U (prefix length %d exceeds packet size %u)",
peer->host, prefixlen, (uint)(lim - pnt));
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
}
/* Fill in the labels */
@@ -264,12 +264,12 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
peer->host, prefixlen);
bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_INVAL_NETWORK);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_LABEL_LENGTH;
}
if ((afi == AFI_IP && p.prefixlen > 32)
|| (afi == AFI_IP6 && p.prefixlen > 128))
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
/* Fetch prefix from NLRI packet */
memcpy(&p.u.prefix, pnt + llen, psize - llen);
@@ -340,8 +340,8 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
BGP_ERR_UPDATE_RCV,
"%s [Error] Update packet error / L-U (%zu data remaining after parsing)",
peer->host, lim - pnt);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
}
- return 0;
+ return BGP_NLRI_PARSE_OK;
}
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index b89edfe459..4fff2faa7e 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -139,7 +139,7 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr,
/* When packet overflow occurs return immediately. */
if (pnt + BGP_ADDPATH_ID_LEN > lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
addpath_id = ntohl(*((uint32_t *)pnt));
pnt += BGP_ADDPATH_ID_LEN;
@@ -155,7 +155,7 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr,
BGP_ERR_UPDATE_RCV,
"%s [Error] Update packet error / VPN (prefix length %d less than VPN min length)",
peer->host, prefixlen);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
}
/* sanity check against packet data */
@@ -164,7 +164,7 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr,
BGP_ERR_UPDATE_RCV,
"%s [Error] Update packet error / VPN (prefix length %d exceeds packet size %u)",
peer->host, prefixlen, (uint)(lim - pnt));
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
}
/* sanity check against storage for the IP address portion */
@@ -175,7 +175,7 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr,
peer->host,
prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8,
sizeof(p.u));
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
}
/* Sanity check against max bitlen of the address family */
@@ -186,7 +186,7 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr,
peer->host,
prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8,
p.family, prefix_blen(&p));
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
}
/* Copy label to prefix. */
@@ -245,7 +245,7 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr,
BGP_ERR_UPDATE_RCV,
"%s [Error] Update packet error / VPN (%zu data remaining after parsing)",
peer->host, lim - pnt);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
}
return 0;
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 6cbb2ec068..8c709f57f2 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -308,7 +308,7 @@ int bgp_nlri_parse(struct peer *peer, struct attr *attr,
case SAFI_FLOWSPEC:
return bgp_nlri_parse_flowspec(peer, attr, packet, mp_withdraw);
}
- return -1;
+ return BGP_NLRI_PARSE_ERROR;
}
/*
@@ -1568,10 +1568,11 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
nlri_ret = bgp_nlri_parse(peer, &attr, &nlris[i], 1);
break;
default:
- nlri_ret = -1;
+ nlri_ret = BGP_NLRI_PARSE_ERROR;
}
- if (nlri_ret < 0) {
+ if (nlri_ret < BGP_NLRI_PARSE_OK
+ && nlri_ret != BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW) {
flog_err(BGP_ERR_UPDATE_RCV,
"%s [Error] Error parsing NLRI", peer->host);
if (peer->status == Established)
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 9fa0aaa4fd..fead5fe75f 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -4202,7 +4202,7 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
/* When packet overflow occurs return immediately. */
if (pnt + BGP_ADDPATH_ID_LEN > lim)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
addpath_id = ntohl(*((uint32_t *)pnt));
pnt += BGP_ADDPATH_ID_LEN;
@@ -4220,7 +4220,7 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
BGP_ERR_UPDATE_RCV,
"%s [Error] Update packet error (wrong prefix length %d for afi %u)",
peer->host, p.prefixlen, packet->afi);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
}
/* Packet size overflow check. */
@@ -4232,7 +4232,7 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
BGP_ERR_UPDATE_RCV,
"%s [Error] Update packet error (prefix length %d overflows packet)",
peer->host, p.prefixlen);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
}
/* Defensive coding, double-check the psize fits in a struct
@@ -4242,7 +4242,7 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
BGP_ERR_UPDATE_RCV,
"%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
peer->host, p.prefixlen, sizeof(p.u));
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
}
/* Fetch prefix from NLRI packet. */
@@ -4307,10 +4307,14 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
BGP_ROUTE_NORMAL, NULL, NULL, 0,
NULL);
- /* Address family configuration mismatch or maximum-prefix count
- overflow. */
+ /* Do not send BGP notification twice when maximum-prefix count
+ * overflow. */
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
+ return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
+
+ /* Address family configuration mismatch. */
if (ret < 0)
- return -1;
+ return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
}
/* Packet length consistency check. */
@@ -4319,10 +4323,10 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
BGP_ERR_UPDATE_RCV,
"%s [Error] Update packet error (prefix length mismatch with total length)",
peer->host);
- return -1;
+ return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
}
- return 0;
+ return BGP_NLRI_PARSE_OK;
}
static struct bgp_static *bgp_static_new(void)
@@ -10177,7 +10181,11 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
return;
}
- table = bgp->rib[afi][safi];
+ /* labeled-unicast routes live in the unicast table */
+ if (safi == SAFI_LABELED_UNICAST)
+ table = bgp->rib[afi][SAFI_UNICAST];
+ else
+ table = bgp->rib[afi][safi];
output_count = filtered_count = 0;
subgrp = peer_subgroup(peer, afi, safi);
@@ -10401,10 +10409,6 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
if (use_json)
json = json_object_new_object();
- /* labeled-unicast routes live in the unicast table */
- if (safi == SAFI_LABELED_UNICAST)
- safi = SAFI_UNICAST;
-
if (!peer || !peer->afc[afi][safi]) {
if (use_json) {
json_object_string_add(
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index dfef9a8f79..534dd76215 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -72,6 +72,24 @@ enum bgp_show_adj_route_type {
*/
#define BGP_MAX_LABELS 2
+/* Error codes for handling NLRI */
+#define BGP_NLRI_PARSE_OK 0
+#define BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW -1
+#define BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW -2
+#define BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH -3
+#define BGP_NLRI_PARSE_ERROR_PACKET_LENGTH -4
+#define BGP_NLRI_PARSE_ERROR_LABEL_LENGTH -5
+#define BGP_NLRI_PARSE_ERROR_EVPN_MISSING_TYPE -6
+#define BGP_NLRI_PARSE_ERROR_EVPN_TYPE2_SIZE -7
+#define BGP_NLRI_PARSE_ERROR_EVPN_TYPE3_SIZE -8
+#define BGP_NLRI_PARSE_ERROR_EVPN_TYPE4_SIZE -9
+#define BGP_NLRI_PARSE_ERROR_EVPN_TYPE5_SIZE -10
+#define BGP_NLRI_PARSE_ERROR_FLOWSPEC_IPV6_NOT_SUPPORTED -11
+#define BGP_NLRI_PARSE_ERROR_FLOWSPEC_NLRI_SIZELIMIT -12
+#define BGP_NLRI_PARSE_ERROR_FLOWSPEC_BAD_FORMAT -13
+#define BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY -14
+#define BGP_NLRI_PARSE_ERROR -32
+
/* Ancillary information to struct bgp_info,
* used for uncommonly used data (aggregation, MPLS, etc.)
* and lazily allocated to save memory.
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index 2e0bb1ae62..196d1449b7 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -1133,7 +1133,7 @@ DEFPY (no_rpki_cache,
{
struct cache *cache_p = find_cache(preference);
- if (!cache) {
+ if (!cache_p) {
vty_out(vty, "Could not find cache %ld\n", preference);
return CMD_WARNING;
}
@@ -1189,9 +1189,23 @@ DEFUN (show_rpki_cache_server,
struct cache *cache;
for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
- vty_out(vty, "host: %s port: %s\n",
- cache->tr_config.tcp_config->host,
- cache->tr_config.tcp_config->port);
+ if (cache->type == TCP) {
+ vty_out(vty, "host: %s port: %s\n",
+ cache->tr_config.tcp_config->host,
+ cache->tr_config.tcp_config->port);
+
+ } else if (cache->type == SSH) {
+ vty_out(vty,
+ "host: %s port: %d username: %s "
+ "server_hostkey_path: %s client_privkey_path: %s\n",
+ cache->tr_config.ssh_config->host,
+ cache->tr_config.ssh_config->port,
+ cache->tr_config.ssh_config->username,
+ cache->tr_config.ssh_config
+ ->server_hostkey_path,
+ cache->tr_config.ssh_config
+ ->client_privkey_path);
+ }
}
return CMD_SUCCESS;
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index e54a873e15..bdac903b99 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -3834,6 +3834,13 @@ ALIAS_HIDDEN(neighbor_nexthop_self_force,
"Disable the next hop calculation for this neighbor\n"
"Set the next hop to self for reflected routes\n")
+ALIAS_HIDDEN(neighbor_nexthop_self_force,
+ neighbor_nexthop_self_all_hidden_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> next-hop-self all",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Disable the next hop calculation for this neighbor\n"
+ "Set the next hop to self for reflected routes\n")
+
DEFUN (no_neighbor_nexthop_self,
no_neighbor_nexthop_self_cmd,
"no neighbor <A.B.C.D|X:X::X:X|WORD> next-hop-self",
@@ -3875,6 +3882,13 @@ ALIAS_HIDDEN(no_neighbor_nexthop_self_force,
"Disable the next hop calculation for this neighbor\n"
"Set the next hop to self for reflected routes\n")
+ALIAS_HIDDEN(no_neighbor_nexthop_self_force,
+ no_neighbor_nexthop_self_all_hidden_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> next-hop-self all",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Disable the next hop calculation for this neighbor\n"
+ "Set the next hop to self for reflected routes\n")
+
/* neighbor as-override */
DEFUN (neighbor_as_override,
neighbor_as_override_cmd,
@@ -7838,7 +7852,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
json, "ribMemory",
ents * sizeof(struct bgp_node));
- ents = listcount(bgp->peer);
+ ents = bgp->af_peer_count[afi][safi];
json_object_int_add(json, "peerCount", ents);
json_object_int_add(json, "peerMemory",
ents * sizeof(struct peer));
@@ -7878,7 +7892,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
bgp_node)));
/* Peer related usage */
- ents = listcount(bgp->peer);
+ ents = bgp->af_peer_count[afi][safi];
vty_out(vty, "Peers %ld, using %s of memory\n",
ents,
mtype_memstr(
@@ -8296,7 +8310,7 @@ const char *afi_safi_json(afi_t afi, safi_t safi)
}
/* Show BGP peer's information. */
-enum show_type { show_all, show_peer };
+enum show_type { show_all, show_peer, show_ipv4_all, show_ipv6_all, show_ipv4_peer, show_ipv6_peer };
static void bgp_show_peer_afi_orf_cap(struct vty *vty, struct peer *p,
afi_t afi, safi_t safi,
@@ -9001,7 +9015,7 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, uint8_t use_json,
} else {
if ((p->as_type == AS_SPECIFIED) || (p->as_type == AS_EXTERNAL)
|| (p->as_type == AS_INTERNAL))
- vty_out(vty, "remote AS %u, ", p->as);
+ vty_out(vty, "remote AS %" PRIu32 ", ", p->as);
else
vty_out(vty, "remote AS Unspecified, ");
vty_out(vty, "local AS %u%s%s, ",
@@ -10690,6 +10704,14 @@ static int bgp_show_neighbor(struct vty *vty, struct bgp *bgp,
struct listnode *node, *nnode;
struct peer *peer;
int find = 0;
+ afi_t afi = AFI_MAX;
+ safi_t safi = SAFI_MAX;
+
+ if (type == show_ipv4_peer || type == show_ipv4_all) {
+ afi = AFI_IP;
+ } else if (type == show_ipv6_peer || type == show_ipv6_all) {
+ afi = AFI_IP6;
+ }
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
@@ -10717,10 +10739,45 @@ static int bgp_show_neighbor(struct vty *vty, struct bgp *bgp,
}
}
break;
+ case show_ipv4_peer:
+ case show_ipv6_peer:
+ FOREACH_SAFI (safi) {
+ if (peer->afc[afi][safi]) {
+ if (conf_if) {
+ if ((peer->conf_if
+ && !strcmp(peer->conf_if, conf_if))
+ || (peer->hostname
+ && !strcmp(peer->hostname, conf_if))) {
+ find = 1;
+ bgp_show_peer(vty, peer, use_json,
+ json);
+ break;
+ }
+ } else {
+ if (sockunion_same(&peer->su, su)) {
+ find = 1;
+ bgp_show_peer(vty, peer, use_json,
+ json);
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case show_ipv4_all:
+ case show_ipv6_all:
+ FOREACH_SAFI (safi) {
+ if (peer->afc[afi][safi]) {
+ bgp_show_peer(vty, peer, use_json, json);
+ break;
+ }
+ }
+ break;
}
}
- if (type == show_peer && !find) {
+ if ((type == show_peer || type == show_ipv4_peer ||
+ type == show_ipv6_peer) && !find) {
if (use_json)
json_object_boolean_true_add(json, "bgpNoSuchNeighbor");
else
@@ -10788,7 +10845,8 @@ static void bgp_show_all_instances_neighbors_vty(struct vty *vty,
: bgp->name);
}
- if (type == show_peer) {
+ if (type == show_peer || type == show_ipv4_peer ||
+ type == show_ipv6_peer) {
ret = str2sockunion(ip_str, &su);
if (ret < 0)
bgp_show_neighbor(vty, bgp, type, NULL, ip_str,
@@ -10797,7 +10855,7 @@ static void bgp_show_all_instances_neighbors_vty(struct vty *vty,
bgp_show_neighbor(vty, bgp, type, &su, NULL,
use_json, json);
} else {
- bgp_show_neighbor(vty, bgp, show_all, NULL, NULL,
+ bgp_show_neighbor(vty, bgp, type, NULL, NULL,
use_json, json);
}
}
@@ -10884,6 +10942,7 @@ DEFUN (show_ip_bgp_neighbors,
char *vrf = NULL;
char *sh_arg = NULL;
enum show_type sh_type;
+ afi_t afi = AFI_MAX;
uint8_t uj = use_json(argc, argv);
@@ -10894,13 +10953,29 @@ DEFUN (show_ip_bgp_neighbors,
vrf = argv[idx + 1]->arg;
idx++;
+
+ if (argv_find(argv, argc, "ipv4", &idx)) {
+ sh_type = show_ipv4_all;
+ afi = AFI_IP;
+ } else if (argv_find(argv, argc, "ipv6", &idx)) {
+ sh_type = show_ipv6_all;
+ afi = AFI_IP6;
+ } else {
+ sh_type = show_all;
+ }
+
if (argv_find(argv, argc, "A.B.C.D", &idx)
|| argv_find(argv, argc, "X:X::X:X", &idx)
|| argv_find(argv, argc, "WORD", &idx)) {
sh_type = show_peer;
sh_arg = argv[idx]->arg;
- } else
- sh_type = show_all;
+ }
+
+ if (sh_type == show_peer && afi == AFI_IP) {
+ sh_type = show_ipv4_peer;
+ } else if (sh_type == show_peer && afi == AFI_IP6) {
+ sh_type = show_ipv6_peer;
+ }
return bgp_show_neighbor_vty(vty, vrf, sh_type, sh_arg, uj);
}
@@ -11405,11 +11480,11 @@ static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group)
conf = group->conf;
if (conf->as_type == AS_SPECIFIED || conf->as_type == AS_EXTERNAL) {
- vty_out(vty, "\nBGP peer-group %s, remote AS %d\n", group->name,
- conf->as);
+ vty_out(vty, "\nBGP peer-group %s, remote AS %" PRIu32 "\n",
+ group->name, conf->as);
} else if (conf->as_type == AS_INTERNAL) {
- vty_out(vty, "\nBGP peer-group %s, remote AS %d\n", group->name,
- group->bgp->as);
+ vty_out(vty, "\nBGP peer-group %s, remote AS %" PRIu32 "\n",
+ group->name, group->bgp->as);
} else {
vty_out(vty, "\nBGP peer-group %s\n", group->name);
}
@@ -12795,6 +12870,8 @@ void bgp_vty_init(void)
/* "neighbor next-hop-self force" commands. */
install_element(BGP_NODE, &neighbor_nexthop_self_force_hidden_cmd);
install_element(BGP_NODE, &no_neighbor_nexthop_self_force_hidden_cmd);
+ install_element(BGP_NODE, &neighbor_nexthop_self_all_hidden_cmd);
+ install_element(BGP_NODE, &no_neighbor_nexthop_self_all_hidden_cmd);
install_element(BGP_IPV4_NODE, &neighbor_nexthop_self_force_cmd);
install_element(BGP_IPV4_NODE, &no_neighbor_nexthop_self_force_cmd);
install_element(BGP_IPV4M_NODE, &neighbor_nexthop_self_force_cmd);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index a82dd51cc8..94aadda3d6 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -671,6 +671,7 @@ struct peer_af *peer_af_create(struct peer *peer, afi_t afi, safi_t safi)
{
struct peer_af *af;
int afid;
+ struct bgp *bgp;
if (!peer)
return NULL;
@@ -679,6 +680,7 @@ struct peer_af *peer_af_create(struct peer *peer, afi_t afi, safi_t safi)
if (afid >= BGP_AF_MAX)
return NULL;
+ bgp = peer->bgp;
assert(peer->peer_af_array[afid] == NULL);
/* Allocate new peer af */
@@ -689,6 +691,7 @@ struct peer_af *peer_af_create(struct peer *peer, afi_t afi, safi_t safi)
af->safi = safi;
af->afid = afid;
af->peer = peer;
+ bgp->af_peer_count[afi][safi]++;
return af;
}
@@ -711,6 +714,7 @@ int peer_af_delete(struct peer *peer, afi_t afi, safi_t safi)
{
struct peer_af *af;
int afid;
+ struct bgp *bgp;
if (!peer)
return -1;
@@ -723,6 +727,7 @@ int peer_af_delete(struct peer *peer, afi_t afi, safi_t safi)
if (!af)
return -1;
+ bgp = peer->bgp;
bgp_stop_announce_route_timer(af);
if (PAF_SUBGRP(af)) {
@@ -734,6 +739,9 @@ int peer_af_delete(struct peer *peer, afi_t afi, safi_t safi)
update_subgroup_remove_peer(af->subgroup, af);
+ if (bgp->af_peer_count[afi][safi])
+ bgp->af_peer_count[afi][safi]--;
+
peer->peer_af_array[afid] = NULL;
XFREE(MTYPE_BGP_PEER_AF, af);
return 0;
@@ -3660,6 +3668,7 @@ static const struct peer_flag_action peer_flag_action_list[] = {
{PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset},
{PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset},
{PEER_FLAG_ENFORCE_FIRST_AS, 0, peer_change_reset_in},
+ {PEER_FLAG_IFPEER_V6ONLY, 0, peer_change_reset},
{PEER_FLAG_ROUTEADV, 0, peer_change_none},
{PEER_FLAG_TIMER, 0, peer_change_none},
{PEER_FLAG_TIMER_CONNECT, 0, peer_change_none},
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index fd2157ab9c..a6f0e92da3 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -97,6 +97,9 @@ enum bgp_af_index {
for (afi = AFI_IP; afi < AFI_MAX; afi++) \
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+#define FOREACH_SAFI(safi) \
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+
/* BGP master for system wide configurations and variables. */
struct bgp_master {
/* BGP instance list. */
@@ -370,6 +373,9 @@ struct bgp {
#define BGP_CONFIG_VRF_TO_VRF_EXPORT (1 << 8)
#define BGP_DEFAULT_NAME "default"
+ /* BGP per AF peer count */
+ uint32_t af_peer_count[AFI_MAX][SAFI_MAX];
+
/* Route table for next-hop lookup cache. */
struct bgp_table *nexthop_cache_table[AFI_MAX];
diff --git a/changelog-auto.in b/changelog-auto.in
index 73ba179c3a..27907e1dcd 100644
--- a/changelog-auto.in
+++ b/changelog-auto.in
@@ -6,6 +6,29 @@ frr (@VERSION@-0) UNRELEASED; urgency=medium
-- FRRouting-Dev <dev@lists.frrouting.org> Thu, 25 Oct 2018 16:36:50 +0200
+frr (6.0-3) testing; urgency=medium
+
+ * bgpd: Fix 'show bgp ipv4/ipv6 neighbors' to show only v4 or v6 neighbors
+ * bgpd: Fix display issue when showing labeled-unicast routes
+ * bgpd: Fix incorrect # peers in 'show bgp ipv6 summary' output
+ * bgpd: Fix issue with remote-private-as in combination with local-as
+ * bgpd: Fix memory error when prepending to AS-path
+ * bgpd: Improve error handling when using maximum-prefix
+ * ldpd: Fix startup permissions error on OpenBSD
+ * ldpd: add support for FreeBSD IP_BINDANY
+ * ospfd: Fix incorrect display of millisecond time values
+ * tools: Fix incorrect systemd dependencies causing failure to start on boot
+ * vtysh: Fix unnecessary reconnection under multi-instance OSPF
+ * watchfrr: Fix multi-instance support when using new init script
+ * zebra: Fix a display bug in 'show ip route ... json'
+ * zebra: Fix compilation issue on OpenBSD
+ * zebra: Fix issue with missed selection of system-sourced routes
+ * zebra: Fix race condition in label manager
+ * zebra: Reliability improvements to pseudowire route recovery
+ * zebra: Tweak metric values for macvlan devices
+
+ -- Quentin Young <qlyoung@cumulusnetworks.com> Tue, 7 May 2019 16:31:00 -0500
+
frr (6.0-2) testing; urgency=medium
* add install-info to build deps
diff --git a/configure.ac b/configure.ac
index 72747550dd..ef76b5b209 100755
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@
##
AC_PREREQ(2.60)
-AC_INIT(frr, 6.0.2, [https://github.com/frrouting/frr/issues])
+AC_INIT(frr, 6.0.3, [https://github.com/frrouting/frr/issues])
PACKAGE_URL="https://frrouting.org/"
AC_SUBST(PACKAGE_URL)
PACKAGE_FULLNAME="FRRouting"
@@ -1974,6 +1974,7 @@ AC_SUBST(CFG_SBIN)
AC_SUBST(CFG_STATE)
AC_SUBST(CFG_MODULE)
AC_DEFINE_UNQUOTED(MODULE_PATH, "$CFG_MODULE", path to modules)
+AC_DEFINE_UNQUOTED(WATCHFRR_SH_PATH, "${CFG_SBIN%/}/watchfrr.sh", path to watchfrr.sh)
dnl ------------------------------------
dnl Enable RPKI and add librtr to libs
diff --git a/doc/developer/_static/overrides.css b/doc/developer/_static/overrides.css
index 0d871c961a..1d702bb6e9 100644
--- a/doc/developer/_static/overrides.css
+++ b/doc/developer/_static/overrides.css
@@ -3,6 +3,237 @@ div.body {
max-width: none;
}
+/* Palette URL: http://paletton.com/#uid=70p0p0kt6uvcDRAlhBavokxLJ6w */
+
+:root {
+--primary-0: #F36F16; /* Main Primary color */
+--primary-1: #FFC39A;
+--primary-2: #FF9A55;
+--primary-3: #A34403;
+--primary-4: #341500;
+--primary-9: #FFF3EB;
+
+--secondary-1-0: #F39C16; /* Main Secondary color (1) */
+--secondary-1-1: #FFD79A;
+--secondary-1-2: #FFBC55;
+--secondary-1-3: #A36403;
+--secondary-1-4: #341F00;
+--secondary-1-9: #FFF7EB;
+
+--secondary-2-0: #1A599F; /* Main Secondary color (2) */
+--secondary-2-1: #92B9E5;
+--secondary-2-2: #477CB8;
+--secondary-2-3: #0A386B;
+--secondary-2-4: #011122;
+--secondary-2-9: #E3EBF4;
+
+--complement-0: #0E9A83; /* Main Complement color */
+--complement-1: #8AE4D4;
+--complement-2: #3CB4A0;
+--complement-3: #026857;
+--complement-4: #00211B;
+--complement-9: #E0F4F0;
+}
+
+/* new */
+
+body {
+ font-family: "Fira Sans", Helvetica, Arial, sans-serif;
+ font-weight:400;
+}
+h1, h2, h3, h4, h5, h6 {
+ font-family: "Fira Sans", Helvetica, Arial, sans-serif;
+ font-weight:500;
+}
+code, pre, tt {
+ font-family: "Fira Mono";
+}
+h1 {
+ background-color:var(--secondary-1-1);
+ border-bottom:1px solid var(--secondary-1-0);
+ font-weight:300;
+}
+h2 {
+ margin-top:36pt;
+}
+
+a,
+a:hover,
+a:visited,
+.code-block-caption a.headerlink:hover,
+.rst-content dl:not(.docutils) dt .headerlink {
+ color: var(--complement-0);
+}
+.code-block-caption a.headerlink {
+ visibility:hidden;
+}
+
+/* admonitions */
+
+.admonition.warning {
+ border:1px dashed var(--primary-2);
+}
+.admonition.warning .admonition-title {
+ color: var(--primary-3);
+ background-color: var(--primary-1);
+}
+.admonition.note,
+.admonition.hint {
+ border:1px dashed var(--complement-2);
+}
+.admonition.note .admonition-title,
+.admonition.hint .admonition-title {
+ color: var(--complement-3);
+ background-color: var(--complement-1);
+}
+.admonition.seealso,
+div.seealso {
+ background-color:var(--complement-9);
+}
+.admonition.seealso .admonition-title {
+ color: var(--complement-3);
+ background-color:var(--complement-1);
+ border-bottom:1px solid var(--complement-2);
+}
+.admonition.admonition-todo .admonition-title {
+ background-image: repeating-linear-gradient(
+ 135deg,
+ #ffa,
+ #ffa 14.14213452px,
+ #bbb 14.14213452px,
+ #bbb 28.28427124px
+ );
+ color:#000;
+}
+.admonition.admonition-todo {
+ background-image: repeating-linear-gradient(
+ 135deg,
+ #ffd,
+ #ffd 14.14213452px,
+ #eed 14.14213452px,
+ #eed 28.28427124px
+ );
+}
+
+.rst-content dl .admonition p.last {
+ margin-bottom:0 !important;
+}
+
+/* file block */
+
+.code-block-caption {
+/* border-radius: 4px; */
+ font-style:italic;
+ font-weight:300;
+ border-bottom: 1px solid var(--secondary-2-1);
+ background-color: var(--secondary-2-9);
+ padding:2px 8px;
+}
+
+/* navbar */
+
+.wy-nav-side {
+ background-color: var(--secondary-1-4);
+ border-right:2px solid var(--primary-3);
+}
+.wy-menu-vertical a,
+.wy-menu-vertical a:visited,
+.wy-menu-vertical a:hover,
+.wy-side-nav-search>a,
+.wy-side-nav-search .wy-dropdown>a {
+ color: var(--primary-0);
+}
+
+nav div.wy-side-nav-search {
+ background-color: #eee;
+}
+nav div.wy-side-scroll {
+ background-color: var(--secondary-1-4);
+}
+nav .wy-menu-vertical a:hover {
+ background-color:var(--primary-0);
+ color:var(--primary-4);
+}
+nav .wy-menu-vertical li.current ul a:hover {
+ background-color:var(--secondary-1-2);
+ color:var(--primary-4);
+}
+nav .wy-menu-vertical li.current ul a {
+ background-color:var(--secondary-1-1);
+ color:var(--primary-3);
+}
+nav .wy-menu-vertical li.on a:hover,
+nav .wy-menu-vertical li.current>a:hover {
+ background-color:#fcfcfc;
+}
+.wy-side-nav-search input[type=text] {
+ border-color:var(--primary-2);
+}
+.wy-menu-vertical li.toctree-l1.current>a {
+ border-top:1px solid var(--secondary-1-3);
+ border-bottom:1px solid var(--secondary-1-3);
+}
+.wy-menu-vertical li.toctree-l2.current>a {
+ background-color:var(--secondary-1-2);
+}
+.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a {
+ background-color:var(--secondary-1-9);
+}
+
+.wy-nav-content {
+ padding: 25pt 40pt;
+}
+div[role=navigation] > hr {
+ display:none;
+}
+div[role=navigation] {
+ margin-bottom:15pt;
+}
+h1 {
+ margin-left:-40pt;
+ margin-right:-40pt;
+ padding:5pt 40pt 5pt 40pt;
+}
+
+.rst-content pre.literal-block, .rst-content div[class^='highlight'] {
+ border-color:var(--secondary-1-1);
+}
+
+span.pre {
+ color: var(--complement-3);
+}
pre {
- background-color: #e2e2e2;
+ background-color: var(--secondary-1-9);
+ border-color: var(--secondary-1-1);
+}
+.highlight .p { color: var(--secondary-2-3); }
+.highlight .k { color: var(--secondary-2-0); }
+.highlight .kt { color: var(--complement-0); }
+.highlight .cm { color: var(--primary-3); }
+.highlight .ow { color: var(--primary-3); }
+.highlight .na { color: var(--primary-2); }
+.highlight .nv { color: var(--complement-0); }
+
+strong {
+ font-weight:500;
+}
+.rst-content dl:not(.docutils) dt {
+ font-family:Fira Mono;
+ font-weight:600;
+ background-color:var(--secondary-2-9);
+ color:var(--secondary-2-3);
+ border-top:2px solid var(--secondary-2-2);
+}
+dt code.descname {
+ color: var(--secondary-2-4);
+}
+
+@media (min-width: 1200px) {
+ .container { width: auto; }
+}
+@media (min-width: 992px) {
+ .container { width: auto; }
+}
+@media (min-width: 768px) {
+ .container { width: auto; }
}
diff --git a/doc/developer/conf.py b/doc/developer/conf.py
index 61253c4b2f..6a339480fa 100644
--- a/doc/developer/conf.py
+++ b/doc/developer/conf.py
@@ -167,12 +167,19 @@ todo_include_todos = True
# a list of builtin themes.
html_theme = 'default'
+try:
+ import sphinx_rtd_theme
+
+ html_theme = 'sphinx_rtd_theme'
+except ImportError:
+ pass
+
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
-html_theme_options = {
- 'sidebarbgcolor': '#374249'
-}
+#html_theme_options = {
+# 'sidebarbgcolor': '#374249'
+#}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
diff --git a/doc/manpages/watchfrr.rst b/doc/manpages/watchfrr.rst
index f0b733298d..dceb423f82 100644
--- a/doc/manpages/watchfrr.rst
+++ b/doc/manpages/watchfrr.rst
@@ -22,21 +22,6 @@ In order to avoid restarting the daemons in quick succession, you can supply the
OPTIONS
=======
-The following 3 options specify scripts that |DAEMON| uses to perform start/stop/restart actions. These options are mandatory unless the --dry option is used:
-
-.. option:: -s command, --start-command command
-
- Supply a Bourne shell command to start a single daemon. The command string should contain the '%s' placeholder to be sub‐ stituted with the daemon name.
-
-.. option:: -k command, --kill-command command
-
- Supply a Bourne shell command to stop a single daemon. The command string should contain the '%s' placeholder to be substituted with the daemon name.
-
-.. option:: -r command, --restart command
-
- Supply a Bourne shell command to restart a single daemon. The command string should contain the '%s' placeholder to be substituted with the daemon name.
-
-Other options:
.. option:: --dry
@@ -92,6 +77,20 @@ Other options:
Display the usage information and exit.
+The following 3 options specify scripts that |DAEMON| uses to perform start/stop/restart actions. Reasonable default values are built into watchfrr, so the use of these options should no longer be necessary:
+
+.. option:: -s command, --start-command command
+
+ Supply a Bourne shell command to start a single daemon. The command string should contain the '%s' placeholder to be substituted with the daemon name.
+
+.. option:: -k command, --kill-command command
+
+ Supply a Bourne shell command to stop a single daemon. The command string should contain the '%s' placeholder to be substituted with the daemon name.
+
+.. option:: -r command, --restart command
+
+ Supply a Bourne shell command to restart a single daemon. The command string should contain the '%s' placeholder to be substituted with the daemon name.
+
PREVIOUS OPTIONS
================
Prior versions of |DAEMON| supported some additional options that no longer exist:::
diff --git a/doc/user/_static/overrides.css b/doc/user/_static/overrides.css
index 41fcc66f8d..638f61986f 100644
--- a/doc/user/_static/overrides.css
+++ b/doc/user/_static/overrides.css
@@ -3,10 +3,6 @@ div.body {
max-width: none;
}
-pre {
- background-color: #e2e2e2;
-}
-
/* styling for the protocols vs. OS table in overview.rst */
/* first, general bits */
div.body td.mark {
@@ -40,6 +36,7 @@ td.mark span {
border: 1px dotted #666;
width: 36pt;
margin:auto;
+ text-align:center;
}
table.mark tr td:first-child {
padding-left:1.5em;
@@ -61,3 +58,238 @@ li span.mark {
width: 36pt;
text-align: center;
}
+
+/* Palette URL: http://paletton.com/#uid=70p0p0kt6uvcDRAlhBavokxLJ6w */
+
+:root {
+--primary-0: #F36F16; /* Main Primary color */
+--primary-1: #FFC39A;
+--primary-2: #FF9A55;
+--primary-3: #A34403;
+--primary-4: #341500;
+--primary-9: #FFF3EB;
+
+--secondary-1-0: #F39C16; /* Main Secondary color (1) */
+--secondary-1-1: #FFD79A;
+--secondary-1-2: #FFBC55;
+--secondary-1-3: #A36403;
+--secondary-1-4: #341F00;
+--secondary-1-9: #FFF7EB;
+
+--secondary-2-0: #1A599F; /* Main Secondary color (2) */
+--secondary-2-1: #92B9E5;
+--secondary-2-2: #477CB8;
+--secondary-2-3: #0A386B;
+--secondary-2-4: #011122;
+--secondary-2-9: #E3EBF4;
+
+--complement-0: #0E9A83; /* Main Complement color */
+--complement-1: #8AE4D4;
+--complement-2: #3CB4A0;
+--complement-3: #026857;
+--complement-4: #00211B;
+--complement-9: #E0F4F0;
+}
+
+/* new */
+
+body {
+ font-family: "Fira Sans", Helvetica, Arial, sans-serif;
+ font-weight:400;
+}
+h1, h2, h3, h4, h5, h6 {
+ font-family: "Fira Sans", Helvetica, Arial, sans-serif;
+ font-weight:500;
+}
+code, pre, tt {
+ font-family: "Fira Mono";
+}
+h1 {
+ background-color:var(--secondary-1-1);
+ border-bottom:1px solid var(--secondary-1-0);
+ font-weight:300;
+}
+h2 {
+ margin-top:36pt;
+}
+
+a,
+a:hover,
+a:visited,
+.code-block-caption a.headerlink:hover,
+.rst-content dl:not(.docutils) dt .headerlink {
+ color: var(--complement-0);
+}
+.code-block-caption a.headerlink {
+ visibility:hidden;
+}
+
+/* admonitions */
+
+.admonition.warning {
+ border:1px dashed var(--primary-2);
+}
+.admonition.warning .admonition-title {
+ color: var(--primary-3);
+ background-color: var(--primary-1);
+}
+.admonition.note,
+.admonition.hint {
+ border:1px dashed var(--complement-2);
+}
+.admonition.note .admonition-title,
+.admonition.hint .admonition-title {
+ color: var(--complement-3);
+ background-color: var(--complement-1);
+}
+.admonition.seealso,
+div.seealso {
+ background-color:var(--complement-9);
+}
+.admonition.seealso .admonition-title {
+ color: var(--complement-3);
+ background-color:var(--complement-1);
+ border-bottom:1px solid var(--complement-2);
+}
+.admonition.admonition-todo .admonition-title {
+ background-image: repeating-linear-gradient(
+ 135deg,
+ #ffa,
+ #ffa 14.14213452px,
+ #bbb 14.14213452px,
+ #bbb 28.28427124px
+ );
+ color:#000;
+}
+.admonition.admonition-todo {
+ background-image: repeating-linear-gradient(
+ 135deg,
+ #ffd,
+ #ffd 14.14213452px,
+ #eed 14.14213452px,
+ #eed 28.28427124px
+ );
+}
+
+.rst-content dl .admonition p.last {
+ margin-bottom:0 !important;
+}
+
+/* file block */
+
+.code-block-caption {
+/* border-radius: 4px; */
+ font-style:italic;
+ font-weight:300;
+ border-bottom: 1px solid var(--secondary-2-1);
+ background-color: var(--secondary-2-9);
+ padding:2px 8px;
+}
+
+/* navbar */
+
+.wy-nav-side {
+ background-color: var(--secondary-1-4);
+ border-right:2px solid var(--primary-3);
+}
+.wy-menu-vertical a,
+.wy-menu-vertical a:visited,
+.wy-menu-vertical a:hover,
+.wy-side-nav-search>a,
+.wy-side-nav-search .wy-dropdown>a {
+ color: var(--primary-0);
+}
+
+nav div.wy-side-nav-search {
+ background-color: #eee;
+}
+nav div.wy-side-scroll {
+ background-color: var(--secondary-1-4);
+}
+nav .wy-menu-vertical a:hover {
+ background-color:var(--primary-0);
+ color:var(--primary-4);
+}
+nav .wy-menu-vertical li.current ul a:hover {
+ background-color:var(--secondary-1-2);
+ color:var(--primary-4);
+}
+nav .wy-menu-vertical li.current ul a {
+ background-color:var(--secondary-1-1);
+ color:var(--primary-3);
+}
+nav .wy-menu-vertical li.on a:hover,
+nav .wy-menu-vertical li.current>a:hover {
+ background-color:#fcfcfc;
+}
+.wy-side-nav-search input[type=text] {
+ border-color:var(--primary-2);
+}
+.wy-menu-vertical li.toctree-l1.current>a {
+ border-top:1px solid var(--secondary-1-3);
+ border-bottom:1px solid var(--secondary-1-3);
+}
+.wy-menu-vertical li.toctree-l2.current>a {
+ background-color:var(--secondary-1-2);
+}
+.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a {
+ background-color:var(--secondary-1-9);
+}
+
+.wy-nav-content {
+ padding: 25pt 40pt;
+}
+div[role=navigation] > hr {
+ display:none;
+}
+div[role=navigation] {
+ margin-bottom:15pt;
+}
+h1 {
+ margin-left:-40pt;
+ margin-right:-40pt;
+ padding:5pt 40pt 5pt 40pt;
+}
+
+.rst-content pre.literal-block, .rst-content div[class^='highlight'] {
+ border-color:var(--secondary-1-1);
+}
+
+span.pre {
+ color: var(--complement-3);
+}
+pre {
+ background-color: var(--secondary-1-9);
+ border-color: var(--secondary-1-1);
+}
+.highlight .p { color: var(--secondary-2-3); }
+.highlight .k { color: var(--secondary-2-0); }
+.highlight .kt { color: var(--complement-0); }
+.highlight .cm { color: var(--primary-3); }
+.highlight .ow { color: var(--primary-3); }
+.highlight .na { color: var(--primary-2); }
+.highlight .nv { color: var(--complement-0); }
+
+strong {
+ font-weight:500;
+}
+.rst-content dl:not(.docutils) dt {
+ font-family:Fira Mono;
+ font-weight:600;
+ background-color:var(--secondary-2-9);
+ color:var(--secondary-2-3);
+ border-top:2px solid var(--secondary-2-2);
+}
+dt code.descname {
+ color: var(--secondary-2-4);
+}
+
+@media (min-width: 1200px) {
+ .container { width: auto; }
+}
+@media (min-width: 992px) {
+ .container { width: auto; }
+}
+@media (min-width: 768px) {
+ .container { width: auto; }
+}
diff --git a/doc/user/conf.py b/doc/user/conf.py
index 2231989fe5..635dbaa3c7 100644
--- a/doc/user/conf.py
+++ b/doc/user/conf.py
@@ -168,12 +168,19 @@ todo_include_todos = True
# a list of builtin themes.
html_theme = 'default'
+try:
+ import sphinx_rtd_theme
+
+ html_theme = 'sphinx_rtd_theme'
+except ImportError:
+ pass
+
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
-html_theme_options = {
- 'sidebarbgcolor': '#374249'
-}
+#html_theme_options = {
+# 'sidebarbgcolor': '#374249'
+#}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
diff --git a/doc/user/setup.rst b/doc/user/setup.rst
index 8b27a8f771..acc8217ec4 100644
--- a/doc/user/setup.rst
+++ b/doc/user/setup.rst
@@ -70,13 +70,14 @@ This file has several parts. Here is an example:
bfdd_options=" --daemon -A 127.0.0.1"
# The list of daemons to watch is automatically generated by the init script.
- watchfrr_enable=yes
- watchfrr_options=(-d -r /usr/sbin/servicebBfrrbBrestartbB%s -s /usr/sbin/servicebBfrrbBstartbB%s -k /usr/sbin/servicebBfrrbBstopbB%s -b bB)
+ #watchfrr_options=""
- # If valgrind_enable is 'yes' the frr daemons will be started via valgrind.
- # The use case for doing so is tracking down memory leaks, etc in frr.
- valgrind_enable=no
- valgrind=/usr/bin/valgrind
+ # for debugging purposes, you can specify a "wrap" command to start instead
+ # of starting the daemon directly, e.g. to use valgrind on ospfd:
+ # ospfd_wrap="/usr/bin/valgrind"
+ # or you can use "all_wrap" for all daemons, e.g. to use perf record:
+ # all_wrap="/usr/bin/perf record --call-graph -"
+ # the normal daemon command is added to this at the end.
Breaking this file down:
@@ -99,22 +100,8 @@ from the service script. Usually daemons will have ``--daemon`` and ``-A
<address>`` specified in order to daemonize and listen for VTY commands on a
particular address.
-::
-
- # The list of daemons to watch is automatically generated by the init script.
- watchfrr_enable=yes
- watchfrr_options=(-d -r /usr/sbin/servicebBfrrbBrestartbB%s -s /usr/sbin/servicebBfrrbBstartbB%s -k /usr/sbin/servicebBfrrbBstopbB%s -b bB)
-
-Options for the ``watchfrr``, the watchdog daemon.
-
-::
-
- valgrind_enable=no
- valgrind=/usr/bin/valgrind
-
-Whether or not to start FRR daemons under Valgrind. This is primarily useful
-for gathering information for bug reports and for developers.
-``valgrind_enable`` should be ``no`` for production use.
+The remaining file content regarding `watchfrr_options` and `*_wrap` settings
+should not normally be needed; refer to the comments in case they are.
Services
--------
diff --git a/doc/user/vtysh.rst b/doc/user/vtysh.rst
index 07109a0e54..6d569f5fb0 100644
--- a/doc/user/vtysh.rst
+++ b/doc/user/vtysh.rst
@@ -22,6 +22,37 @@ administrator with an external editor.
have effect for vtysh) need to be manually updated in :file:`vtysh.conf`.
+Pager usage
+===========
+
+*vtysh* can call an external paging program (e.g. *more* or *less*) to
+paginate long output from commands. This feature used to be enabled by
+default but is now controlled by the ``VTYSH_PAGER`` environment variable
+and the :clicmd:`terminal paginate` command:
+
+.. envvar:: VTYSH_PAGER
+
+ If set, the ``VTYSH_PAGER`` environment variable causes *vtysh* to pipe
+ output from commands through the given command. Note that this happens
+ regardless of the length of the output. As such, standard pager behavior
+ (particularly waiting at the end of output) tends to be annoying to the
+ user. Using ``less -EFX`` is recommended for a better user experience.
+
+ If this environment variable is unset, *vtysh* defaults to not using any
+ pager.
+
+ This variable should be set by the user according to their preferences,
+ in their :file:`~/.profile` file.
+
+.. index:: [no] terminal paginate
+.. clicmd:: [no] terminal paginate
+
+ Enables/disables vtysh output pagination. This command is intended to
+ be placed in :file:`vtysh.conf` to set a system-wide default. If this
+ is enabled but ``VTYSH_PAGER`` is not set, the system default pager
+ (likely ``more`` or ``/usr/bin/pager``) will be used.
+
+
Permissions and setup requirements
==================================
diff --git a/include/linux/if_addr.h b/include/linux/if_addr.h
new file mode 100644
index 0000000000..a924606f36
--- /dev/null
+++ b/include/linux/if_addr.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_IF_ADDR_H
+#define __LINUX_IF_ADDR_H
+
+#include <linux/types.h>
+#include <linux/netlink.h>
+
+struct ifaddrmsg {
+ __u8 ifa_family;
+ __u8 ifa_prefixlen; /* The prefix length */
+ __u8 ifa_flags; /* Flags */
+ __u8 ifa_scope; /* Address scope */
+ __u32 ifa_index; /* Link index */
+};
+
+/*
+ * Important comment:
+ * IFA_ADDRESS is prefix address, rather than local interface address.
+ * It makes no difference for normally configured broadcast interfaces,
+ * but for point-to-point IFA_ADDRESS is DESTINATION address,
+ * local address is supplied in IFA_LOCAL attribute.
+ *
+ * IFA_FLAGS is a u32 attribute that extends the u8 field ifa_flags.
+ * If present, the value from struct ifaddrmsg will be ignored.
+ */
+enum {
+ IFA_UNSPEC,
+ IFA_ADDRESS,
+ IFA_LOCAL,
+ IFA_LABEL,
+ IFA_BROADCAST,
+ IFA_ANYCAST,
+ IFA_CACHEINFO,
+ IFA_MULTICAST,
+ IFA_FLAGS,
+ IFA_RT_PRIORITY, /* u32, priority/metric for prefix route */
+ __IFA_MAX,
+};
+
+#define IFA_MAX (__IFA_MAX - 1)
+
+/* ifa_flags */
+#define IFA_F_SECONDARY 0x01
+#define IFA_F_TEMPORARY IFA_F_SECONDARY
+
+#define IFA_F_NODAD 0x02
+#define IFA_F_OPTIMISTIC 0x04
+#define IFA_F_DADFAILED 0x08
+#define IFA_F_HOMEADDRESS 0x10
+#define IFA_F_DEPRECATED 0x20
+#define IFA_F_TENTATIVE 0x40
+#define IFA_F_PERMANENT 0x80
+#define IFA_F_MANAGETEMPADDR 0x100
+#define IFA_F_NOPREFIXROUTE 0x200
+#define IFA_F_MCAUTOJOIN 0x400
+#define IFA_F_STABLE_PRIVACY 0x800
+
+struct ifa_cacheinfo {
+ __u32 ifa_prefered;
+ __u32 ifa_valid;
+ __u32 cstamp; /* created timestamp, hundredths of seconds */
+ __u32 tstamp; /* updated timestamp, hundredths of seconds */
+};
+
+/* backwards compatibility for userspace */
+#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
+#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
+
+#endif
diff --git a/include/subdir.am b/include/subdir.am
index 731785d4b4..0d7fed2852 100644
--- a/include/subdir.am
+++ b/include/subdir.am
@@ -1,4 +1,5 @@
noinst_HEADERS += \
+ include/linux/if_addr.h \
include/linux/if_bridge.h \
include/linux/if_link.h \
include/linux/lwtunnel.h \
diff --git a/ldpd/labelmapping.c b/ldpd/labelmapping.c
index 944f93331f..5e1b422a41 100644
--- a/ldpd/labelmapping.c
+++ b/ldpd/labelmapping.c
@@ -37,7 +37,7 @@ enqueue_pdu(struct nbr *nbr, uint16_t type, struct ibuf *buf, uint16_t size)
struct ldp_hdr *ldp_hdr;
ldp_hdr = ibuf_seek(buf, 0, sizeof(struct ldp_hdr));
- ldp_hdr->length = htons(size);
+ ldp_hdr->length = htons(size - LDP_HDR_DEAD_LEN);
evbuf_enqueue(&nbr->tcp->wbuf, buf);
}
@@ -65,7 +65,7 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh)
/* real size will be set up later */
err |= gen_ldp_hdr(buf, 0);
- size = LDP_HDR_PDU_LEN;
+ size = LDP_HDR_SIZE;
first = 0;
}
diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c
index 56af76d94e..c16d92f28b 100644
--- a/ldpd/ldpe.c
+++ b/ldpd/ldpe.c
@@ -139,6 +139,16 @@ ldpe(void)
void
ldpe_init(struct ldpd_init *init)
{
+#ifdef __OpenBSD__
+ /* This socket must be open before dropping privileges. */
+ global.pfkeysock = pfkey_init();
+ if (sysdep.no_pfkey == 0) {
+ pfkey_ev = NULL;
+ thread_add_read(master, ldpe_dispatch_pfkey, NULL, global.pfkeysock,
+ &pfkey_ev);
+ }
+#endif
+
/* drop privileges */
ldpe_privs.user = init->user;
ldpe_privs.group = init->group;
@@ -159,14 +169,6 @@ ldpe_init(struct ldpd_init *init)
fatal("inet_pton");
if (inet_pton(AF_INET6, AllRouters_v6, &global.mcast_addr_v6) != 1)
fatal("inet_pton");
-#ifdef __OpenBSD__
- global.pfkeysock = pfkey_init();
- if (sysdep.no_pfkey == 0) {
- pfkey_ev = NULL;
- thread_add_read(master, ldpe_dispatch_pfkey, NULL, global.pfkeysock,
- &pfkey_ev);
- }
-#endif
/* mark sockets as closed */
global.ipv4.ldp_disc_socket = -1;
diff --git a/ldpd/socket.c b/ldpd/socket.c
index bebd7a7d61..78a07b1ed4 100644
--- a/ldpd/socket.c
+++ b/ldpd/socket.c
@@ -268,9 +268,18 @@ sock_set_bindany(int fd, int enable)
return (-1);
}
return (0);
+#elif defined(IP_BINDANY)
+ frr_elevate_privs(&ldpd_privs) {
+ if (setsockopt(fd, IPPROTO_IP, IP_BINDANY, &enable, sizeof(int))
+ < 0) {
+ log_warn("%s: error setting IP_BINDANY", __func__);
+ return (-1);
+ }
+ }
#else
- log_warnx("%s: missing SO_BINDANY and IP_FREEBIND, unable to bind "
- "to a nonlocal IP address", __func__);
+ log_warnx(
+ "%s: missing SO_BINDANY, IP_FREEBIND and IP_BINDANY, unable to bind to a nonlocal IP address",
+ __func__);
return (-1);
#endif /* HAVE_SO_BINDANY */
}
diff --git a/lib/command.c b/lib/command.c
index 850980bd4e..ead8cf5efe 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -2542,8 +2542,6 @@ DEFUN (config_log_syslog,
{
int idx_log_levels = 2;
- disable_log_file();
-
if (argc == 3) {
int level;
if ((level = level_match(argv[idx_log_levels]->arg))
diff --git a/lib/if.h b/lib/if.h
index a861cf2d85..a52023d054 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -345,6 +345,8 @@ DECLARE_QOBJ_TYPE(interface)
DECLARE_HOOK(if_add, (struct interface * ifp), (ifp))
DECLARE_KOOH(if_del, (struct interface * ifp), (ifp))
+#define METRIC_MAX (~0)
+
/* Connected address structure. */
struct connected {
/* Attached interface. */
@@ -392,6 +394,13 @@ struct connected {
/* Label for Linux 2.2.X and upper. */
char *label;
+
+ /*
+ * Used for setting the connected route's cost. If the metric
+ * here is set to METRIC_MAX the connected route falls back to
+ * "struct interface"
+ */
+ uint32_t metric;
};
/* Nbr Connected address structure. */
diff --git a/lib/log.c b/lib/log.c
index 1619ad36ec..6c468f5e2d 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -29,6 +29,7 @@
#include "memory.h"
#include "command.h"
#include "lib_errors.h"
+#include "lib/hook.h"
#ifndef SUNOS_5
#include <sys/un.h>
@@ -40,6 +41,10 @@
DEFINE_MTYPE_STATIC(LIB, ZLOG, "Logging")
+/* hook for external logging */
+DEFINE_HOOK(zebra_ext_log, (int priority, const char *format, va_list args),
+ (priority, format, args));
+
static int logfile_fd = -1; /* Used in signal handler. */
struct zlog *zlog_default = NULL;
@@ -207,6 +212,9 @@ void vzlog(int priority, const char *format, va_list args)
tsctl.already_rendered = 0;
struct zlog *zl = zlog_default;
+ /* call external hook */
+ hook_call(zebra_ext_log, priority, format, args);
+
/* When zlog_default is also NULL, use stderr for logging. */
if (zl == NULL) {
tsctl.precision = 0;
diff --git a/lib/log.h b/lib/log.h
index 7b21a0ce37..0551c0ebc3 100644
--- a/lib/log.h
+++ b/lib/log.h
@@ -26,6 +26,12 @@
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
+#include <stdarg.h>
+#include "lib/hook.h"
+
+/* Hook for external logging function */
+DECLARE_HOOK(zebra_ext_log, (int priority, const char *format, va_list args),
+ (priority, format, args));
/* Here is some guidance on logging levels to use:
*
diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c
index 3a42712748..13297aa344 100644
--- a/nhrpd/nhrp_interface.c
+++ b/nhrpd/nhrp_interface.c
@@ -323,9 +323,11 @@ int nhrp_interface_delete(int cmd, struct zclient *client, zebra_size_t length,
return 0;
debugf(NHRP_DEBUG_IF, "if-delete: %s", ifp->name);
- if_set_index(ifp, ifp->ifindex);
+
nhrp_interface_update(ifp);
- /* if_delete(ifp); */
+
+ if_set_index(ifp, IFINDEX_INTERNAL);
+
return 0;
}
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index 24584f6713..7d77c38660 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -920,6 +920,23 @@ static void ospf_vl_if_delete(struct ospf_vl_data *vl_data)
vlink_count--;
}
+/* for a defined area, count the number of configured vl
+ */
+int ospf_vl_count(struct ospf *ospf, struct ospf_area *area)
+{
+ int count = 0;
+ struct ospf_vl_data *vl_data;
+ struct listnode *node;
+
+ for (ALL_LIST_ELEMENTS_RO(ospf->vlinks, node, vl_data)) {
+ if (area
+ && !IPV4_ADDR_SAME(&vl_data->vl_area_id, &area->area_id))
+ continue;
+ count++;
+ }
+ return count;
+}
+
/* Look up vl_data for given peer, optionally qualified to be in the
* specified area. NULL area returns first found..
*/
diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h
index 73ded208cf..b88d405875 100644
--- a/ospfd/ospf_interface.h
+++ b/ospfd/ospf_interface.h
@@ -300,6 +300,7 @@ extern struct ospf_vl_data *ospf_vl_data_new(struct ospf_area *,
struct in_addr);
extern struct ospf_vl_data *ospf_vl_lookup(struct ospf *, struct ospf_area *,
struct in_addr);
+extern int ospf_vl_count(struct ospf *ospf, struct ospf_area *area);
extern void ospf_vl_data_free(struct ospf_vl_data *);
extern void ospf_vl_add(struct ospf *, struct ospf_vl_data *);
extern void ospf_vl_delete(struct ospf *, struct ospf_vl_data *);
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index fb9770d09a..0ac9d4ac82 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -1199,14 +1199,17 @@ DEFUN (no_ospf_area_vlink,
return CMD_WARNING_CONFIG_FAILED;
}
+ vl_data = ospf_vl_lookup(ospf, area, vl_config.vl_peer);
+ if (!vl_data) {
+ vty_out(vty, "Virtual link does not exist\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
if (argc <= 5) {
/* Basic VLink no command */
/* Thats all folks! - BUGS B. strikes again!!!*/
- if ((vl_data = ospf_vl_lookup(ospf, area, vl_config.vl_peer)))
- ospf_vl_delete(ospf, vl_data);
-
+ ospf_vl_delete(ospf, vl_data);
ospf_area_check_free(ospf, vl_config.area_id);
-
return CMD_SUCCESS;
}
@@ -3021,13 +3024,13 @@ static int show_ip_ospf_common(struct vty *vty, struct ospf *ospf,
if (ospf->stub_router_startup_time
!= OSPF_STUB_ROUTER_UNCONFIGURED)
json_object_int_add(
- json_vrf, "postStartEnabledMsecs",
- ospf->stub_router_startup_time / 1000);
+ json_vrf, "postStartEnabledSecs",
+ ospf->stub_router_startup_time);
if (ospf->stub_router_shutdown_time
!= OSPF_STUB_ROUTER_UNCONFIGURED)
json_object_int_add(
- json_vrf, "preShutdownEnabledMsecs",
- ospf->stub_router_shutdown_time / 1000);
+ json_vrf, "preShutdownEnabledSecs",
+ ospf->stub_router_shutdown_time);
} else {
vty_out(vty,
" Stub router advertisement is configured\n");
@@ -3486,8 +3489,8 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
json_object_int_add(json_interface_sub, "cost",
oi->output_cost);
json_object_int_add(
- json_interface_sub, "transmitDelayMsecs",
- 1000 / OSPF_IF_PARAM(oi, transmit_delay));
+ json_interface_sub, "transmitDelaySecs",
+ OSPF_IF_PARAM(oi, transmit_delay));
json_object_string_add(json_interface_sub, "state",
lookup_msg(ospf_ism_state_msg,
oi->state, NULL));
@@ -3591,20 +3594,20 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
if (OSPF_IF_PARAM(oi, fast_hello) == 0)
json_object_int_add(
json_interface_sub, "timerMsecs",
- 1000 / OSPF_IF_PARAM(oi, v_hello));
+ OSPF_IF_PARAM(oi, v_hello) * 1000);
else
json_object_int_add(
json_interface_sub, "timerMsecs",
1000 / OSPF_IF_PARAM(oi, fast_hello));
json_object_int_add(json_interface_sub,
- "timerDeadMsecs",
- 1000 / OSPF_IF_PARAM(oi, v_wait));
+ "timerDeadSecs",
+ OSPF_IF_PARAM(oi, v_wait));
json_object_int_add(json_interface_sub,
- "timerWaitMsecs",
- 1000 / OSPF_IF_PARAM(oi, v_wait));
+ "timerWaitSecs",
+ OSPF_IF_PARAM(oi, v_wait));
json_object_int_add(
- json_interface_sub, "timerRetransmit",
- 1000 / OSPF_IF_PARAM(oi, retransmit_interval));
+ json_interface_sub, "timerRetransmitSecs",
+ OSPF_IF_PARAM(oi, retransmit_interval));
} else {
vty_out(vty, " Timer intervals configured,");
vty_out(vty, " Hello ");
@@ -5099,12 +5102,15 @@ DEFUN (show_ip_ospf_neighbor_id,
uint8_t uj = use_json(argc, argv);
struct listnode *node = NULL;
int ret = CMD_SUCCESS;
+ int idx_router_id = 0;
+
+ argv_find(argv, argc, "A.B.C.D", &idx_router_id);
for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) {
if (!ospf->oi_running)
continue;
- ret = show_ip_ospf_neighbor_id_common(vty, ospf, 0, argv, uj,
- 0);
+ ret = show_ip_ospf_neighbor_id_common(vty, ospf, idx_router_id,
+ argv, uj, 0);
}
return ret;
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index b7dfedd15a..6f4a01becf 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -895,6 +895,7 @@ void ospf_area_check_free(struct ospf *ospf, struct in_addr area_id)
area = ospf_area_lookup_by_area_id(ospf, area_id);
if (area && listcount(area->oiflist) == 0 && area->ranges->top == NULL
+ && !ospf_vl_count(ospf, area)
&& area->shortcut_configured == OSPF_SHORTCUT_DEFAULT
&& area->external_routing == OSPF_AREA_DEFAULT
&& area->no_summary == 0 && area->default_cost == 1
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index ad60e8e3a6..30d66c835b 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -152,6 +152,8 @@ static int pim_zebra_if_del(int command, struct zclient *zclient,
if (!if_is_operative(ifp))
pim_if_addr_del_all(ifp);
+ if_set_index(ifp, IFINDEX_INTERNAL);
+
return 0;
}
diff --git a/redhat/daemons b/redhat/daemons
deleted file mode 100644
index 068d74d596..0000000000
--- a/redhat/daemons
+++ /dev/null
@@ -1,84 +0,0 @@
-# This file tells the frr package which daemons to start.
-#
-# Entries are in the format: <daemon>=(yes|no|priority)
-# 0, "no" = disabled
-# 1, "yes" = highest priority
-# 2 .. 10 = lower priorities
-#
-# For daemons which support multiple instances, a 2nd line listing
-# the instances can be added. Eg for ospfd:
-# ospfd=yes
-# ospfd_instances="1,2"
-#
-# Priorities were suggested by Dancer <dancer@zeor.simegen.com>.
-# They're used to start the FRR daemons in more than one step
-# (for example start one or two at network initialization and the
-# rest later). The number of FRR daemons being small, priorities
-# must be between 1 and 9, inclusive (or the initscript has to be
-# changed). /etc/init.d/frr then can be started as
-#
-# /etc/init.d/frr <start|stop|restart|<priority>>
-#
-# where priority 0 is the same as 'stop', priority 10 or 'start'
-# means 'start all'
-#
-# Sample configurations for these daemons can be found in
-# /usr/share/doc/frr/examples/.
-#
-# ATTENTION:
-#
-# When activation a daemon at the first time, a config file, even if it is
-# empty, has to be present *and* be owned by the user and group "frr", else
-# the daemon will not be started by /etc/init.d/frr. The permissions should
-# be u=rw,g=r,o=.
-# When using "vtysh" such a config file is also needed. It should be owned by
-# group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too.
-#
-watchfrr_enable=yes
-watchfrr_options="-r '/usr/lib/frr/frr restart %s' -s '/usr/lib/frr/frr start %s' -k '/usr/lib/frr/frr stop %s'"
-#
-zebra=no
-bgpd=no
-ospfd=no
-ospf6d=no
-ripd=no
-ripngd=no
-isisd=no
-ldpd=no
-pimd=no
-nhrpd=no
-eigrpd=no
-babeld=no
-sharpd=no
-pbrd=no
-staticd=no
-bfdd=no
-
-#
-# Command line options for the daemons
-#
-zebra_options=("-A 127.0.0.1")
-bgpd_options=("-A 127.0.0.1")
-ospfd_options=("-A 127.0.0.1")
-ospf6d_options=("-A ::1")
-ripd_options=("-A 127.0.0.1")
-ripngd_options=("-A ::1")
-isisd_options=("-A 127.0.0.1")
-ldpd_options=("-A 127.0.0.1")
-pimd_options=("-A 127.0.0.1")
-nhrpd_options=("-A 127.0.0.1")
-eigrpd_options=("-A 127.0.0.1")
-babeld_options=("-A 127.0.0.1")
-sharpd_options=("-A 127.0.0.1")
-pbrd_options=("-A 127.0.0.1")
-staticd_options=("-A 127.0.0.1")
-bfdd_options=("-A 127.0.0.1")
-
-#
-# If the vtysh_enable is yes, then the unified config is read
-# and applied if it exists. If no unified frr.conf exists
-# then the per-daemon <daemon>.conf files are used)
-# If vtysh_enable is no or non-existant, the frr.conf is ignored.
-# it is highly suggested to have this set to yes
-vtysh_enable=yes
-
diff --git a/redhat/frr.init b/redhat/frr.init
deleted file mode 100755
index 4c4d59c77a..0000000000
--- a/redhat/frr.init
+++ /dev/null
@@ -1,577 +0,0 @@
-#!/bin/bash
-#
-# /etc/rc.d/init.d/frr
-#
-# Start/Stop the FRR Routing daemons
-# <any general comments about this init script>
-#
-# chkconfig: 2345 15 85
-#
-# description: FRRouting (FRR) is a routing suite for IP routing protocols
-# like BGP, OSPF, RIP and others. This script contols the main
-# daemon "frr" as well as the individual protocol daemons.
-#
-### BEGIN INIT INFO
-# Provides: frr
-# Required-Start: $local_fs $network $syslog
-# Required-Stop: $local_fs $syslog
-# Should-Start: $syslog
-# Should-Stop: $network $syslog
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: Start/Stop the FRR Routing daemons
-# Description: FRRouting (FRR) is a routing suite for IP routing protocols
-# like BGP, OSPF, RIP and others. This script contols the main
-# daemon "frr" as well as the individual protocol daemons.
-### END INIT INFO
-
-PATH=/bin:/usr/bin:/sbin:/usr/sbin
-D_PATH=/usr/lib/frr
-C_PATH=/etc/frr
-V_PATH=/var/run/frr
-
-# Local Daemon selection may be done by using /etc/frr/daemons.
-# See /usr/share/doc/frr/README.Debian.gz for further information.
-# Keep zebra first and do not list watchfrr!
-DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd pimd pbrd ldpd nhrpd eigrpd babeld staticd sharpd bfdd"
-MAX_INSTANCES=5
-RELOAD_SCRIPT=/usr/lib/frr/frr-reload.py
-
-. /etc/init.d/functions
-
-# Print the name of the pidfile.
-pidfile()
-{
- echo "$V_PATH/$1.pid"
-}
-
-# Print the name of the vtysh.
-vtyfile()
-{
- echo "$V_PATH/$1.vty"
-}
-
-# Check if daemon is started by using the pidfile.
-started()
-{
- [ ! -e `pidfile $1` ] && return 3
- if [ -n "$2" ] && [ "$2" == "log" ]; then
- status -p `pidfile $1` $1 && return 0 || return $?
- else
- kill -0 `cat \`pidfile $1\`` 2> /dev/null || return 1
- return 0
- fi
-}
-
-# Loads the config via vtysh -b if configured to do so.
-vtysh_b ()
-{
- # Rember, that all variables have been incremented by 1 in convert_daemon_prios()
- if [ "$vtysh_enable" = 2 -a -f $C_PATH/frr.conf ]; then
- /usr/bin/vtysh -b -n
- fi
-}
-
-# Check if the daemon is activated and if its executable and config files
-# are in place.
-# params: daemon name
-# returns: 0=ok, 1=error
-check_daemon()
-{
- # If the integrated config file is used the others are not checked.
- if [ -r "$C_PATH/frr.conf" ]; then
- return 0
- fi
-
- # vtysh_enable has no config file nor binary so skip check.
- # (Not sure why vtysh_enable is in this list but does not hurt)
- if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
- # check for daemon binary
- if [ ! -x "$D_PATH/$1" ]; then return 1; fi
-
- # check for config file
- if [ -n "$2" ]; then
- if [ ! -r "$C_PATH/$1-$2.conf" ]; then
- touch "$C_PATH/$1-$2.conf"
- chown frr:frr "$C_PATH/$1-$2.conf"
- fi
- elif [ ! -r "$C_PATH/$1.conf" ]; then
- touch "$C_PATH/$1.conf"
- chown frr:frr "$C_PATH/$1.conf"
- fi
- fi
- return 0
-}
-
-# Starts the server if it's not already running according to the pid file.
-# The Frr daemons creates the pidfile when starting.
-start()
-{
- local dmn inst
- dmn="$1"
- inst="$2"
-
- ulimit -n $MAX_FDS > /dev/null 2> /dev/null
- if [ "$dmn" = "watchfrr" ]; then
-
- # We may need to restart watchfrr if new daemons are added and/or
- # removed
- if started "$dmn" ; then
- stop watchfrr
- else
- # Echo only once. watchfrr is printed in the stop above
- echo -n " $dmn"
- fi
-
- if [ -e /var/run/frr/watchfrr.started ] ; then
- rm /var/run/frr/watchfrr.started
- fi
- # redhat /etc/init.d/functions daemon() re-expands args :(
- # eval "set - $watchfrr_options"
- daemon --pidfile=`pidfile $dmn` "$D_PATH/$dmn" -d "$watchfrr_options"
- RETVAL=$?
- [ $RETVAL -ne 0 ] && break
- for i in `seq 1 10`;
- do
- if [ -e /var/run/frr/watchfrr.started ] ; then
- RETVAL=0
- break
- else
- sleep 1
- fi
- done
- RETVAL=1
- elif [ -n "$inst" ]; then
- echo -n " $dmn-$inst"
- if ! check_daemon $dmn $inst ; then
- echo -n " (binary does not exist)"
- return;
- fi
- daemon --pidfile=`pidfile $dmn-$inst` "$D_PATH/$dmn" -d `eval echo "$""$dmn""_options"` -n "$inst"
- RETVAL=$?
- else
- echo -n " $dmn "
- if ! check_daemon $dmn; then
- echo " (binary does not exist)"
- return;
- fi
- daemon --pidfile=`pidfile $dmn` "$D_PATH/$dmn" -d `eval echo "$""$dmn""_options"`
- RETVAL=$?
- fi
- echo
- [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$dmn
- return $RETVAL
-}
-
-# Stop the daemon given in the parameter, printing its name to the terminal.
-stop()
-{
- local inst
-
- if [ -n "$2" ]; then
- inst="$1-$2"
- else
- inst="$1"
- fi
-
- if ! started "$inst" ; then
- # echo -n " ($inst)"
- return 0
- else
- echo -n " $inst"
- PIDFILE=`pidfile $inst`
- PID=`cat $PIDFILE 2>/dev/null`
- killproc -p "$PIDFILE" "$D_PATH/$1"
- RETVAL=$?
- [ $RETVAL -eq 0 ] && rm -f $lockfile
- rm -f `pidfile $inst`
- rm -f `vtyfile $inst`
- echo
- return $RETVAL
- fi
-}
-
-# Converts values from /etc/frr/daemons to all-numeric values.
-convert_daemon_prios()
-{
- for name in $DAEMONS zebra vtysh_enable watchfrr_enable; do
- # First, assign the value set by the user to $value
- eval value=\${${name}:0:3}
-
- # Daemon not activated or entry missing?
- if [ "$value" = "no" -o "$value" = "" ]; then value=0; fi
-
- # These strings parsed for backwards compatibility.
- if [ "$value" = "yes" -o "$value" = "true" ]; then
- value=1;
- fi
-
- # Zebra is threatened special. It must be between 0=off and the first
- # user assigned value "1" so we increase all other enabled daemons' values.
- if [ "$name" != "zebra" -a "$value" -gt 0 ]; then value=`expr "$value" + 1`; fi
-
- # If e.g. name is zebra then we set "zebra=yes".
- eval $name=$value
- done
-}
-
-# Starts watchfrr for all wanted daemons.
-start_watchfrr()
-{
- local daemon_name
- local daemon_prio
- local found_one
- local daemon_inst
-
- # Start the monitor daemon only if desired.
- if [ 0 -eq "$watchfrr_enable" ]; then
- return
- fi
-
- # Check variable type
- if declare -p watchfrr_options | grep -q '^declare \-a'; then
- # old array support
- watchfrr_options="${watchfrr_options[@]}"
- fi
-
- # Which daemons have been started?
- found_one=0
- for daemon_name in $DAEMONS; do
- eval daemon_prio=\$$daemon_name
- if [ "$daemon_prio" -gt 0 ]; then
- eval "daemon_inst=\${${daemon_name}_instances//,/ }"
- if [ -n "$daemon_inst" ]; then
- for inst in ${daemon_inst}; do
- eval "inst_disable=\${${daemon_name}_${inst}}"
- if [ -z ${inst_disable} ] || [ ${inst_disable} != 0 ]; then
- if check_daemon $daemon_name $inst; then
- watchfrr_options="$watchfrr_options ${daemon_name}-${inst}"
- fi
- fi
- done
- else
- if check_daemon $daemon_name; then
- watchfrr_options="$watchfrr_options $daemon_name"
- fi
- fi
- found_one=1
- fi
- done
-
- # Start if at least one daemon is activated.
- if [ $found_one -eq 1 ]; then
- echo "Starting FRRouting monitor daemon:"
- start watchfrr
- fi
-}
-
-# Stopps watchfrr.
-stop_watchfrr()
-{
- echo "Stopping FRRouting monitor daemon:"
- stop watchfrr
-}
-
-# Stops all daemons that have a lower level of priority than the given.
-# (technically if daemon_prio >= wanted_prio)
-stop_prio()
-{
- local wanted_prio
- local daemon_prio
- local daemon_list
- local daemon_inst
- local inst
-
- if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
- daemon=${BASH_REMATCH[1]}
- inst=${BASH_REMATCH[2]}
- else
- daemon="$2"
- fi
-
- wanted_prio=$1
- daemon_list=${daemon:-$DAEMONS}
-
- echo "Stopping FRRouting daemons (prio:$wanted_prio):"
-
- for prio_i in `seq 10 -1 $wanted_prio`; do
- for daemon_name in $daemon_list; do
- eval daemon_prio=\${${daemon_name}:0:3}
- daemon_inst=""
- if [ $daemon_prio -eq $prio_i ]; then
- eval "daemon_inst=\${${daemon_name}_instances//,/ }"
- if [ -n "$daemon_inst" ]; then
- for i in ${daemon_inst}; do
- if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
- stop "$daemon_name" "$inst"
- elif [ x"$inst" == x ]; then
- stop "$daemon_name" "$i"
- fi
- done
- else
- stop "$daemon_name"
- fi
- fi
- done
- done
-
- if [ -z "$inst" ]; then
- # Now stop other daemons that're prowling, coz the daemons file changed
- echo "Stopping other FRRouting daemons"
- if [ -n "$daemon" ]; then
- eval "file_list_suffix="$V_PATH"/"$daemon*""
- else
- eval "file_list_suffix="$V_PATH/*""
- fi
- for pidfile in $file_list_suffix.pid; do
- if [ -f "$pidfile" ]; then
- filename=${pidfile##*/}
- daemon=${filename%.*}
- echo -n " $daemon"
- killproc -p "$pidfile" "$daemon"
- RETVAL=$?
- [ $RETVAL -eq 0 ] && rm -f $lockfile
- rm -f "$pidfile"
- echo
- fi
- done
- echo -n "Removing remaining .vty files"
- for vtyfile in $file_list_suffix.vty; do
- rm -rf "$vtyfile"
- done
- echo
- fi
-}
-
-# Starts all daemons that have a higher level of priority than the given.
-# (technically if daemon_prio <= wanted_prio)
-start_prio()
-{
- local wanted_prio
- local daemon_prio
- local daemon_list
- local daemon_name
- local daemon_inst
- local inst
-
- if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
- daemon=${BASH_REMATCH[1]}
- inst=${BASH_REMATCH[2]}
- else
- daemon="$2"
- fi
-
- wanted_prio=$1
- daemon_list=${daemon:-$DAEMONS}
-
- echo "Starting FRRouting daemons (prio:$wanted_prio):"
-
- for prio_i in `seq 1 $wanted_prio`; do
- for daemon_name in $daemon_list; do
- eval daemon_prio=\$${daemon_name}
- daemon_inst=""
- if [ $daemon_prio -eq $prio_i ]; then
- eval "daemon_inst=\${${daemon_name}_instances//,/ }"
- if [ -n "$daemon_inst" ]; then
- if [ `echo "$daemon_inst" | wc -w` -gt ${MAX_INSTANCES} ]; then
- echo "Max instances supported is ${MAX_INSTANCES}. Aborting"
- exit 1
- fi
- # Check if we're starting again by switching from single instance
- # to MI version
- if started "$daemon_name"; then
- PIDFILE=`pidfile $daemon_name`
- killproc -p "$PIDFILE" "$daemon_name"
- rm -f `pidfile $1`
- rm -f `vtyfile $1`
- fi
-
- for i in ${daemon_inst}; do
- if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
- start "$daemon_name" "$inst"
- elif [ x"$inst" == x ]; then
- start "$daemon_name" "$i"
- fi
- done
- else
- # Check if we're starting again by switching from
- # single instance to MI version
- eval "file_list_suffix="$V_PATH"/"$daemon_name-*""
- for pidfile in $file_list_suffix.pid; do
- if [ -f "$pidfile" ]; then
- killproc -p "$pidfile" "$daemon_name"
- rm -rf "$pidfile"
- fi
- done
- for vtyfile in $file_list_suffix.vty; do
- rm -rf "$vtyfile"
- done
-
- start "$daemon_name"
- fi
- fi
- done
- done
-}
-
-check_status()
-{
- local daemon_name
- local daemon_prio
- local daemon_inst
- local failed_status=0
-
- if [ -n "$1" ] && [[ "$1" =~ (.*)-(.*) ]]; then
- daemon=${BASH_REMATCH[1]}
- inst=${BASH_REMATCH[2]}
- else
- daemon="$1"
- fi
-
- daemon_list=${daemon:-$DAEMONS}
-
- # Which daemons have been started?
- for daemon_name in $daemon_list; do
- eval daemon_prio=\$$daemon_name
- if [ "$daemon_prio" -gt 0 ]; then
- eval "daemon_inst=\${${daemon_name}_instances//,/ }"
- if [ -n "$daemon_inst" ]; then
- for i in ${daemon_inst}; do
- if [ -n "$inst" -a "$inst" = "$i" ]; then
- started "$1" "log" || failed_status=$?
- elif [ -z "$inst" ]; then
- started "$daemon_name-$i" "log" || failed_status=$?
- fi
- done
- else
- started "$daemon_name" "log" || failed_status=$?
- fi
- fi
- done
-
- # All daemons that need to have been started are up and running
- return $failed_status
-}
-
-#########################################################
-# Main program #
-#########################################################
-
-# Config broken but script must exit silently.
-[ ! -r "$C_PATH/daemons" ] && exit 0
-
-# Load configuration
-. "$C_PATH/daemons"
-
-# Read configuration variable file if it is present
-[ -r /etc/sysconfig/frr ] && . /etc/sysconfig/frr
-
-MAX_INSTANCES=${MAX_INSTANCES:=5}
-
-# Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
-convert_daemon_prios
-
-if [ ! -d $V_PATH ]; then
- echo "Creating $V_PATH"
- mkdir -p $V_PATH
- chown frr:frr $V_PATH
- chmod 755 /$V_PATH
-fi
-
-if [ -n "$3" ] && [ "$3" != "all" ]; then
- dmn="$2"-"$3"
-elif [ -n "$2" ] && [ "$2" != "all" ]; then
- dmn="$2"
-fi
-
-case "$1" in
- start)
- # Try to load this necessary (at least for 2.6) module.
- if [ -d /lib/modules/`uname -r` ] ; then
- echo "Loading capability module if not yet done."
- LC_ALL=C modprobe -a capability 2>&1 | egrep -v "(not found|Can't locate)"
- fi
-
- # Start all daemons
- cd $C_PATH/
- if [ "$2" != "watchfrr" ]; then
- start_prio 10 $dmn
- fi
- start_watchfrr
- vtysh_b
- ;;
-
- 1|2|3|4|5|6|7|8|9|10)
- # Stop/start daemons for the appropriate priority level
- stop_prio $1
- start_prio $1
- vtysh_b
- ;;
-
- stop|0)
- # Stop all daemons at level '0' or 'stop'
- stop_watchfrr
- if [ "$dmn" != "watchfrr" ]; then
- [ -n "${dmn}" ] && eval "${dmn/-/_}=0"
- stop_prio 0 $dmn
- fi
-
- if [ -z "$dmn" -o "$dmn" = "zebra" ]; then
- echo "Removing all routes made by zebra."
- ip route flush proto zebra
- # At least in CentOS/RHEL 6, iproute2 doesn't know
- # about the new protocol names, so we have to flush them
- # by number (it also doesn't support rt_protos.d
- ip route flush proto 186
- ip route flush proto 187
- ip route flush proto 188
- ip route flush proto 189
- ip route flush proto 190
- ip route flush proto 191
- ip route flush proto 192
- ip route flush proto 193
- ip route flush proto 194
- else
- [ -n "$dmn" ] && eval "${dmn/-/_}=0"
- start_watchfrr
- fi
- ;;
-
- reload)
- # Just apply the commands that have changed, no restart necessary
- if [ ! -x "$RELOAD_SCRIPT" ]; then
- echo "frr-reload - reload not supported. Use restart or install frr-pythontools package"
- exit 1
- fi
- NEW_CONFIG_FILE="${2:-$C_PATH/frr.conf}"
- if [ ! -r $NEW_CONFIG_FILE ]; then
- echo "Unable to read configuration file $NEW_CONFIG_FILE. Only supporting integrated config"
- exit 1
- fi
- echo "Applying only incremental changes to running configuration from frr.conf"
- "$RELOAD_SCRIPT" --reload /etc/frr/frr.conf
- exit $?
- ;;
-
- status)
- check_status $dmn
- exit $?
- ;;
-
- restart|force-reload)
- $0 stop $dmn
- sleep 1
- $0 start $dmn
- ;;
-
- *)
- echo "Usage: /etc/init.d/frr {start|stop|status|reload|restart|force-reload|<priority>} [daemon]"
- echo " E.g. '/etc/init.d/frr 5' would start all daemons with a prio 1-5."
- echo " reload applies only modifications from the running config to all daemons."
- echo " reload neither restarts starts any daemon nor starts any new ones."
- echo " Read /usr/share/doc/frr/README.Debian for details."
- exit 1
- ;;
-esac
-
-exit 0
diff --git a/redhat/frr.service b/redhat/frr.service
deleted file mode 100644
index 3ae0aabfe2..0000000000
--- a/redhat/frr.service
+++ /dev/null
@@ -1,23 +0,0 @@
-[Unit]
-Description=FRRouting (FRR)
-After=syslog.target networking.service
-OnFailure=heartbeat-failed@%n.service
-
-[Service]
-Nice=-5
-Type=forking
-NotifyAccess=all
-StartLimitInterval=3m
-StartLimitBurst=3
-TimeoutSec=2m
-WatchdogSec=60s
-RestartSec=5
-Restart=on-abnormal
-LimitNOFILE=1024
-ExecStart=/usr/lib/frr/frr start
-ExecStop=/usr/lib/frr/frr stop
-ExecReload=/usr/lib/frr/frr reload
-
-[Install]
-WantedBy=network-online.target
-
diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in
index 4e68365362..e5407a2cb9 100644
--- a/redhat/frr.spec.in
+++ b/redhat/frr.spec.in
@@ -374,15 +374,13 @@ rm -vf %{buildroot}%{_libdir}/*.la
# install /etc sources
%if "%{initsystem}" == "systemd"
mkdir -p %{buildroot}%{_unitdir}
-install -m644 %{zeb_rh_src}/frr.service %{buildroot}%{_unitdir}/frr.service
-install %{zeb_rh_src}/frr.init %{buildroot}%{_sbindir}/frr
+install -m644 %{zeb_src}/tools/frr.service %{buildroot}%{_unitdir}/frr.service
%else
mkdir -p %{buildroot}%{_initddir}
-install %{zeb_rh_src}/frr.init %{buildroot}%{_sbindir}/frr
-ln -s %{_sbindir}/frr %{buildroot}%{_initddir}/frr
+ln -s %{_sbindir}/frrinit.sh %{buildroot}%{_initddir}/frr
%endif
-install %{zeb_rh_src}/daemons %{buildroot}%{_sysconfdir}/frr
+install %{zeb_src}/tools/etc/frr/daemons %{buildroot}%{_sysconfdir}/frr
# add rpki module to daemon
%if %{with_rpki}
sed -i -e 's/^\(bgpd_options=\)\(.*\)\(".*\)/\1\2 -M rpki\3/' %{buildroot}%{_sysconfdir}/frr/daemons
@@ -471,7 +469,7 @@ zebra_spec_add_service isisd 2608/tcp "ISISd vty"
# Fix bad path in previous config files
# Config files won't get replaced by default, so we do this ugly hack to fix it
-%__sed -i 's|/etc/init.d/|%{_sbindir}/|g' %{configdir}/daemons 2> /dev/null || true
+%__sed -i 's|watchfrr_options=|#watchfrr_options=|g' %{configdir}/daemons 2> /dev/null || true
# With systemd, watchfrr is mandatory. Fix config to make sure it's enabled if
# we install or upgrade to a frr built with systemd
@@ -627,7 +625,6 @@ fi
%else
%{_initddir}/frr
%endif
-%{_sbindir}/frr
%config(noreplace) %{_sysconfdir}/pam.d/frr
%config(noreplace) %{_sysconfdir}/logrotate.d/frr
%{_sbindir}/frr-reload
@@ -663,7 +660,28 @@ fi
%changelog
-* Tue Jan 8 2019 Martin Winter <mwinter@opensourcerouting.org> - %{version}
+
+* Tue May 7 2019 Quentin Young <qlyoung@cumulusnetworks.com> - %{version}
+- bgpd: Fix 'show bgp ipv4/ipv6 neighbors' to show only v4 or v6 neighbors
+- bgpd: Fix display issue when showing labeled-unicast routes
+- bgpd: Fix incorrect # peers in 'show bgp ipv6 summary' output
+- bgpd: Fix issue with remote-private-as in combination with local-as
+- bgpd: Fix memory error when prepending to AS-path
+- bgpd: Improve error handling when using maximum-prefix
+- ldpd: Fix startup permissions error on OpenBSD
+- ldpd: add support for FreeBSD IP_BINDANY
+- ospfd: Fix incorrect display of millisecond time values
+- tools: Fix incorrect systemd dependencies causing failure to start on boot
+- vtysh: Fix unnecessary reconnection under multi-instance OSPF
+- watchfrr: Fix multi-instance support when using new init script
+- zebra: Fix a display bug in 'show ip route ... json'
+- zebra: Fix compilation issue on OpenBSD
+- zebra: Fix issue with missed selection of system-sourced routes
+- zebra: Fix race condition in label manager
+- zebra: Reliability improvements to pseudowire route recovery
+- zebra: Tweak metric values for macvlan devices
+
+* Tue Jan 8 2019 Martin Winter <mwinter@opensourcerouting.org> - 6.0.2
- Security Issue (Denial of Service): Fix BGP Attribute 255 (experimental VNC)
handling
diff --git a/tools/etc/frr/daemons b/tools/etc/frr/daemons
index 9077606633..c40ebb598d 100644
--- a/tools/etc/frr/daemons
+++ b/tools/etc/frr/daemons
@@ -53,7 +53,7 @@ staticd_options="-A 127.0.0.1"
bfdd_options=" -A 127.0.0.1"
# The list of daemons to watch is automatically generated by the init script.
-watchfrr_options="-r '/usr/lib/frr/watchfrr.sh restart %s' -s '/usr/lib/frr/watchfrr.sh start %s' -k '/usr/lib/frr/watchfrr.sh stop %s'"
+#watchfrr_options=""
# for debugging purposes, you can specify a "wrap" command to start instead
# of starting the daemon directly, e.g. to use valgrind on ospfd:
diff --git a/tools/frr.service b/tools/frr.service
index c7568593b3..aa45f420fe 100644
--- a/tools/frr.service
+++ b/tools/frr.service
@@ -1,7 +1,9 @@
[Unit]
Description=FRRouting
Documentation=https://frrouting.readthedocs.io/en/latest/setup.html
-After=networking.service
+Wants=network.target
+After=network-pre.target systemd-sysctl.service
+Before=network.target
OnFailure=heartbeat-failed@%n.service
[Service]
@@ -20,4 +22,4 @@ ExecStop=/usr/lib/frr/frrinit.sh stop
ExecReload=/usr/lib/frr/frrinit.sh reload
[Install]
-WantedBy=network-online.target
+WantedBy=multi-user.target
diff --git a/tools/frrcommon.sh.in b/tools/frrcommon.sh.in
index 588aa6d103..897e6d6558 100644
--- a/tools/frrcommon.sh.in
+++ b/tools/frrcommon.sh.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
#
# This is a "library" of sorts for use by the other FRR shell scripts. It
# has most of the daemon start/stop logic, but expects the following shell
@@ -67,9 +67,9 @@ vtysh_b () {
daemon_inst() {
# note this sets global variables ($dmninst, $daemon, $inst)
dmninst="$1"
- daemon="${dmninst%:*}"
+ daemon="${dmninst%-*}"
inst=""
- [ "$daemon" != "$dmninst" ] && inst="${dmninst#*:}"
+ [ "$daemon" != "$dmninst" ] && inst="${dmninst#*-}"
}
daemon_list() {
@@ -92,9 +92,12 @@ daemon_list() {
enabled="$enabled $daemon"
if [ -n "$inst" ]; then
debug "$daemon multi-instance $inst"
+ oldifs="${IFS}"
+ IFS="${IFS},"
for i in $inst; do
- enabled="$enabled $daemon:$inst"
+ enabled="$enabled $daemon-$i"
done
+ IFS="${oldifs}"
fi
else
debug "$daemon disabled"
@@ -119,7 +122,7 @@ daemon_prep() {
inst="$2"
[ "$daemon" = "watchfrr" ] && return 0
[ -x "$D_PATH/$daemon" ] || {
- log_failure_msg "cannot start $daemon${inst:+ (instance $inst)}: daemon binary not installed\n"
+ log_failure_msg "cannot start $daemon${inst:+ (instance $inst)}: daemon binary not installed"
return 1
}
[ -r "$C_PATH/frr.conf" ] && return 0
@@ -279,7 +282,7 @@ load_old_config() {
}
[ -r "$C_PATH/daemons" ] || {
- log_failure_msg "cannot run $@: $C_PATH/daemons does not exist\n"
+ log_failure_msg "cannot run $@: $C_PATH/daemons does not exist"
exit 1
}
. "$C_PATH/daemons"
@@ -288,6 +291,13 @@ load_old_config "$C_PATH/daemons.conf"
load_old_config "/etc/default/frr"
load_old_config "/etc/sysconfig/frr"
+if { declare -p watchfrr_options 2>/dev/null || true; } | grep -q '^declare \-a'; then
+ log_warning_msg "watchfrr_options contains a bash array value." \
+ "The configured value is intentionally ignored since it is likely wrong." \
+ "Please remove or fix the setting."
+ unset watchfrr_options
+fi
+
#
# other defaults and dispatch
#
diff --git a/tools/frrinit.sh.in b/tools/frrinit.sh.in
index 3dddf5bd44..0f5ed85864 100644
--- a/tools/frrinit.sh.in
+++ b/tools/frrinit.sh.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
#
### BEGIN INIT INFO
# Provides: frr
diff --git a/tools/tarsource.sh b/tools/tarsource.sh
index 110558da0d..2e7ed4411d 100755
--- a/tools/tarsource.sh
+++ b/tools/tarsource.sh
@@ -133,7 +133,7 @@ onexit() {
trap onexit EXIT
tmpdir="`mktemp -d -t frrtar.XXXXXX`"
-if test -d "$src/.git"; then
+if test -e "$src/.git"; then
commit="`git -C \"$src\" rev-parse \"${commit:-HEAD}\"`"
if $dirty; then
diff --git a/tools/watchfrr.sh.in b/tools/watchfrr.sh.in
index 3051d91044..712f962a0a 100644
--- a/tools/watchfrr.sh.in
+++ b/tools/watchfrr.sh.in
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
#
# This is NOT the init script! This is the watchfrr start/stop/restart
# command handler, passed to watchfrr with the -s/-r/-k commands. It is used
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 2a3b74cdb1..b42b56e9ef 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -104,7 +104,7 @@ static int vty_close_pager(struct vty *vty)
return 0;
}
-static void vtysh_pager_envdef(void)
+static void vtysh_pager_envdef(bool fallback)
{
char *pager_defined;
@@ -112,7 +112,7 @@ static void vtysh_pager_envdef(void)
if (pager_defined)
vtysh_pager_name = strdup(pager_defined);
- else
+ else if (fallback)
vtysh_pager_name = strdup(VTYSH_PAGER);
}
@@ -576,7 +576,7 @@ static int vtysh_execute_func(const char *line, int pager)
&& (cmd->daemon == vtysh_client[i].flag)) {
for (vc = &vtysh_client[i]; vc;
vc = vc->next)
- if (vc->fd < 0)
+ if (vc->fd == VTYSH_WAS_ACTIVE)
vtysh_reconnect(vc);
}
if (vtysh_client[i].fd < 0
@@ -2858,7 +2858,7 @@ DEFUN (vtysh_terminal_paginate,
vtysh_pager_name = NULL;
if (strcmp(argv[0]->text, "no"))
- vtysh_pager_envdef();
+ vtysh_pager_envdef(true);
return CMD_SUCCESS;
}
@@ -2878,7 +2878,7 @@ DEFUN (vtysh_terminal_length,
if (!strcmp(argv[0]->text, "no") || !strcmp(argv[1]->text, "no")) {
/* "terminal no length" = use VTYSH_PAGER */
- vtysh_pager_envdef();
+ vtysh_pager_envdef(true);
return CMD_SUCCESS;
}
@@ -2887,7 +2887,7 @@ DEFUN (vtysh_terminal_length,
vty_out(vty,
"%% The \"terminal length\" command is deprecated and its value is ignored.\n"
"%% Please use \"terminal paginate\" instead with OS TTY length handling.\n");
- vtysh_pager_envdef();
+ vtysh_pager_envdef(true);
}
return CMD_SUCCESS;
@@ -3445,6 +3445,7 @@ void vtysh_init_vty(void)
/* set default output */
vty->of = stdout;
+ vtysh_pager_envdef(false);
/* Initialize commands. */
cmd_init(0);
@@ -3773,6 +3774,7 @@ void vtysh_init_vty(void)
/* "write memory" command. */
install_element(ENABLE_NODE, &vtysh_write_memory_cmd);
+ install_element(CONFIG_NODE, &vtysh_terminal_paginate_cmd);
install_element(VIEW_NODE, &vtysh_terminal_paginate_cmd);
install_element(VIEW_NODE, &vtysh_terminal_length_cmd);
install_element(VIEW_NODE, &vtysh_terminal_no_length_cmd);
diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c
index 7e75bed2d6..757d10419a 100644
--- a/watchfrr/watchfrr.c
+++ b/watchfrr/watchfrr.c
@@ -53,6 +53,10 @@
#define DEFAULT_MIN_RESTART 60
#define DEFAULT_MAX_RESTART 600
+#define DEFAULT_RESTART_CMD WATCHFRR_SH_PATH " restart %s"
+#define DEFAULT_START_CMD WATCHFRR_SH_PATH " start %s"
+#define DEFAULT_STOP_CMD WATCHFRR_SH_PATH " stop %s"
+
#define PING_TOKEN "PING"
DEFINE_MGROUP(WATCHFRR, "watchfrr")
@@ -124,6 +128,9 @@ static struct global_state {
.loglevel = DEFAULT_LOGLEVEL,
.min_restart_interval = DEFAULT_MIN_RESTART,
.max_restart_interval = DEFAULT_MAX_RESTART,
+ .restart_command = DEFAULT_RESTART_CMD,
+ .start_command = DEFAULT_START_CMD,
+ .stop_command = DEFAULT_STOP_CMD,
};
typedef enum {
@@ -227,14 +234,17 @@ Otherwise, the interval is doubled (but capped at the -M value).\n\n",
-r, --restart Supply a Bourne shell command to use to restart a single\n\
daemon. The command string should include '%%s' where the\n\
name of the daemon should be substituted.\n\
+ (default: '%s')\n\
-s, --start-command\n\
Supply a Bourne shell to command to use to start a single\n\
daemon. The command string should include '%%s' where the\n\
name of the daemon should be substituted.\n\
+ (default: '%s')\n\
-k, --kill-command\n\
Supply a Bourne shell to command to use to stop a single\n\
daemon. The command string should include '%%s' where the\n\
name of the daemon should be substituted.\n\
+ (default: '%s')\n\
--dry Do not start or restart anything, just log.\n\
-p, --pid-file Set process identifier file name\n\
(default is %s/watchfrr.pid).\n\
@@ -247,7 +257,9 @@ Otherwise, the interval is doubled (but capped at the -M value).\n\n",
-h, --help Display this help and exit\n",
frr_vtydir, DEFAULT_LOGLEVEL, LOG_EMERG, LOG_DEBUG, LOG_DEBUG,
DEFAULT_MIN_RESTART, DEFAULT_MAX_RESTART, DEFAULT_PERIOD,
- DEFAULT_TIMEOUT, DEFAULT_RESTART_TIMEOUT, frr_vtydir);
+ DEFAULT_TIMEOUT, DEFAULT_RESTART_TIMEOUT,
+ DEFAULT_RESTART_CMD, DEFAULT_START_CMD, DEFAULT_STOP_CMD,
+ frr_vtydir);
}
static pid_t run_background(char *shell_cmd)
diff --git a/zebra/connected.c b/zebra/connected.c
index 57bfcc4d16..147715dd16 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -208,6 +208,7 @@ void connected_up(struct interface *ifp, struct connected *ifc)
.ifindex = ifp->ifindex,
.vrf_id = ifp->vrf_id,
};
+ uint32_t metric;
if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
return;
@@ -241,11 +242,13 @@ void connected_up(struct interface *ifp, struct connected *ifc)
break;
}
+ metric = (ifc->metric < (uint32_t)METRIC_MAX) ?
+ ifc->metric : ifp->metric;
rib_add(afi, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, &p,
- NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
+ NULL, &nh, RT_TABLE_MAIN, metric, 0, 0, 0);
rib_add(afi, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, &p,
- NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
+ NULL, &nh, RT_TABLE_MAIN, metric, 0, 0, 0);
if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
char buf[PREFIX_STRLEN];
@@ -274,7 +277,7 @@ void connected_up(struct interface *ifp, struct connected *ifc)
/* Add connected IPv4 route to the interface. */
void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
uint8_t prefixlen, struct in_addr *broad,
- const char *label)
+ const char *label, uint32_t metric)
{
struct prefix_ipv4 *p;
struct connected *ifc;
@@ -286,6 +289,7 @@ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
ifc = connected_new();
ifc->ifp = ifp;
ifc->flags = flags;
+ ifc->metric = metric;
/* If we get a notification from the kernel,
* we can safely assume the address is known to the kernel */
SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
@@ -496,7 +500,7 @@ void connected_delete_ipv4(struct interface *ifp, int flags,
/* Add connected IPv6 route to the interface. */
void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
struct in6_addr *broad, uint8_t prefixlen,
- const char *label)
+ const char *label, uint32_t metric)
{
struct prefix_ipv6 *p;
struct connected *ifc;
@@ -508,6 +512,7 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
ifc = connected_new();
ifc->ifp = ifp;
ifc->flags = flags;
+ ifc->metric = metric;
/* If we get a notification from the kernel,
* we can safely assume the address is known to the kernel */
SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
diff --git a/zebra/connected.h b/zebra/connected.h
index 75b6e05bda..d9c41b328b 100644
--- a/zebra/connected.h
+++ b/zebra/connected.h
@@ -36,7 +36,8 @@ extern struct connected *connected_check_ptp(struct interface *ifp,
extern void connected_add_ipv4(struct interface *ifp, int flags,
struct in_addr *addr, uint8_t prefixlen,
- struct in_addr *broad, const char *label);
+ struct in_addr *broad, const char *label,
+ uint32_t metric);
extern void connected_delete_ipv4(struct interface *ifp, int flags,
struct in_addr *addr, uint8_t prefixlen,
@@ -49,7 +50,8 @@ extern void connected_down(struct interface *ifp, struct connected *ifc);
extern void connected_add_ipv6(struct interface *ifp, int flags,
struct in6_addr *address, struct in6_addr *broad,
- uint8_t prefixlen, const char *label);
+ uint8_t prefixlen, const char *label,
+ uint32_t metric);
extern void connected_delete_ipv6(struct interface *ifp,
struct in6_addr *address,
struct in6_addr *broad, uint8_t prefixlen);
diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c
index 176bb2bbad..d7c6486584 100644
--- a/zebra/if_ioctl.c
+++ b/zebra/if_ioctl.c
@@ -233,7 +233,8 @@ static int if_getaddrs(void)
}
connected_add_ipv4(ifp, flags, &addr->sin_addr,
- prefixlen, dest_pnt, NULL);
+ prefixlen, dest_pnt, NULL,
+ METRIC_MAX);
}
if (ifap->ifa_addr->sa_family == AF_INET6) {
struct sockaddr_in6 *addr;
@@ -255,7 +256,7 @@ static int if_getaddrs(void)
#endif
connected_add_ipv6(ifp, flags, &addr->sin6_addr, NULL,
- prefixlen, NULL);
+ prefixlen, NULL, METRIC_MAX);
}
}
diff --git a/zebra/if_ioctl_solaris.c b/zebra/if_ioctl_solaris.c
index 5a58fe1751..20668183bb 100644
--- a/zebra/if_ioctl_solaris.c
+++ b/zebra/if_ioctl_solaris.c
@@ -298,10 +298,11 @@ static int if_get_addr(struct interface *ifp, struct sockaddr *addr,
/* Set address to the interface. */
if (af == AF_INET)
connected_add_ipv4(ifp, flags, &SIN(addr)->sin_addr, prefixlen,
- (struct in_addr *)dest_pnt, label);
+ (struct in_addr *)dest_pnt, label,
+ METRIC_MAX);
else if (af == AF_INET6)
connected_add_ipv6(ifp, flags, &SIN6(addr)->sin6_addr, NULL,
- prefixlen, label);
+ prefixlen, label, METRIC_MAX);
return 0;
}
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index a15d914243..bed6fbf3d8 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -889,6 +889,7 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
uint8_t flags = 0;
char *label = NULL;
struct zebra_ns *zns;
+ uint32_t metric = METRIC_MAX;
zns = zebra_ns_lookup(ns_id);
ifa = NLMSG_DATA(h);
@@ -996,6 +997,9 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (label && strcmp(ifp->name, label) == 0)
label = NULL;
+ if (tb[IFA_RT_PRIORITY])
+ metric = *(uint32_t *)RTA_DATA(tb[IFA_RT_PRIORITY]);
+
/* Register interface address to the interface. */
if (ifa->ifa_family == AF_INET) {
if (ifa->ifa_prefixlen > IPV4_MAX_BITLEN) {
@@ -1007,7 +1011,8 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (h->nlmsg_type == RTM_NEWADDR)
connected_add_ipv4(ifp, flags, (struct in_addr *)addr,
ifa->ifa_prefixlen,
- (struct in_addr *)broad, label);
+ (struct in_addr *)broad, label,
+ metric);
else
connected_delete_ipv4(
ifp, flags, (struct in_addr *)addr,
@@ -1032,7 +1037,8 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
connected_add_ipv6(ifp, flags,
(struct in6_addr *)addr,
(struct in6_addr *)broad,
- ifa->ifa_prefixlen, label);
+ ifa->ifa_prefixlen, label,
+ metric);
} else
connected_delete_ipv6(ifp, (struct in6_addr *)addr,
(struct in6_addr *)broad,
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index ff035fb353..25007d6c8c 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -194,7 +194,9 @@ const struct message rtm_type_str[] = {{RTM_ADD, "RTM_ADD"},
{RTM_LOSING, "RTM_LOSING"},
{RTM_REDIRECT, "RTM_REDIRECT"},
{RTM_MISS, "RTM_MISS"},
+#ifdef RTM_LOCK
{RTM_LOCK, "RTM_LOCK"},
+#endif /* RTM_LOCK */
#ifdef OLDADD
{RTM_OLDADD, "RTM_OLDADD"},
#endif /* RTM_OLDADD */
@@ -759,7 +761,8 @@ int ifam_read(struct ifa_msghdr *ifam)
connected_add_ipv4(ifp, flags, &addr.sin.sin_addr,
ip_masklen(mask.sin.sin_addr),
&brd.sin.sin_addr,
- (isalias ? ifname : NULL));
+ (isalias ? ifname : NULL),
+ METRIC_MAX);
else
connected_delete_ipv4(ifp, flags, &addr.sin.sin_addr,
ip_masklen(mask.sin.sin_addr),
@@ -776,7 +779,8 @@ int ifam_read(struct ifa_msghdr *ifam)
connected_add_ipv6(ifp, flags, &addr.sin6.sin6_addr,
NULL,
ip6_masklen(mask.sin6.sin6_addr),
- (isalias ? ifname : NULL));
+ (isalias ? ifname : NULL),
+ METRIC_MAX);
else
connected_delete_ipv6(ifp, &addr.sin6.sin6_addr, NULL,
ip6_masklen(mask.sin6.sin6_addr));
diff --git a/zebra/label_manager.c b/zebra/label_manager.c
index 65c85f7dee..1dba0a49f7 100644
--- a/zebra/label_manager.c
+++ b/zebra/label_manager.c
@@ -155,11 +155,9 @@ static int lm_zclient_read(struct thread *t)
/* read response and send it back */
ret = relay_response_back();
- /* on error, schedule another read */
- if (ret == -1)
- if (!zclient->t_read)
- thread_add_read(zclient->master, lm_zclient_read, NULL,
- zclient->sock, &zclient->t_read);
+ /* re-arm read */
+ thread_add_read(zclient->master, lm_zclient_read, NULL,
+ zclient->sock, &zclient->t_read);
return ret;
}
diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c
index 456253cc30..73260634f3 100644
--- a/zebra/zebra_ns.c
+++ b/zebra/zebra_ns.c
@@ -93,6 +93,7 @@ static int zebra_ns_new(struct ns *ns)
zns = zebra_ns_alloc();
ns->info = zns;
zns->ns = ns;
+ zns->ns_id = ns->ns_id;
/* Do any needed per-NS data structure allocation. */
zns->if_table = route_table_init();
diff --git a/zebra/zebra_pw.c b/zebra/zebra_pw.c
index c6db1463f2..24ffa162a6 100644
--- a/zebra/zebra_pw.c
+++ b/zebra/zebra_pw.c
@@ -154,6 +154,7 @@ void zebra_pw_update(struct zebra_pw *pw)
{
if (zebra_pw_check_reachability(pw) < 0) {
zebra_pw_uninstall(pw);
+ zebra_pw_install_failure(pw);
/* wait for NHT and try again later */
} else {
/*
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index ab07549ec2..9e56559522 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1409,7 +1409,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
* from ourselves we don't
* over write this pointer
*/
- dest->selected_fib = NULL;
+ dest->selected_fib = new;
}
/* If install succeeded or system route, cleanup flags
* for prior route. */
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index f787d641b4..ffd8482551 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -374,6 +374,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object *json_labels = NULL;
time_t uptime;
struct tm *tm;
+ rib_dest_t *dest = rib_dest_from_rnode(rn);
uptime = time(NULL);
uptime -= re->uptime;
@@ -398,11 +399,13 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
json_object_boolean_true_add(json_route, "selected");
- if (re->type != ZEBRA_ROUTE_CONNECT) {
- json_object_int_add(json_route, "distance",
- re->distance);
- json_object_int_add(json_route, "metric", re->metric);
- }
+ if (dest->selected_fib == re)
+ json_object_boolean_true_add(json_route,
+ "destSelected");
+
+ json_object_int_add(json_route, "distance",
+ re->distance);
+ json_object_int_add(json_route, "metric", re->metric);
if (re->tag)
json_object_int_add(json_route, "tag", re->tag);
@@ -611,7 +614,9 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
srcdest_rnode2str(rn, buf, sizeof buf));
/* Distance and metric display. */
- if (re->type != ZEBRA_ROUTE_CONNECT)
+ if (((re->type == ZEBRA_ROUTE_CONNECT) &&
+ (re->distance || re->metric)) ||
+ (re->type != ZEBRA_ROUTE_CONNECT))
len += vty_out(vty, " [%u/%u]", re->distance,
re->metric);
} else {
@@ -741,15 +746,14 @@ static void vty_show_ip_route_detail_json(struct vty *vty,
char buf[BUFSIZ];
json = json_object_new_object();
+ json_prefix = json_object_new_array();
RNODE_FOREACH_RE (rn, re) {
- json_prefix = json_object_new_array();
vty_show_ip_route(vty, rn, re, json_prefix);
- prefix2str(&rn->p, buf, sizeof buf);
- json_object_object_add(json, buf, json_prefix);
- json_prefix = NULL;
}
+ prefix2str(&rn->p, buf, sizeof(buf));
+ json_object_object_add(json, buf, json_prefix);
vty_out(vty, "%s\n", json_object_to_json_string_ext(
json, JSON_C_TO_STRING_PRETTY));
json_object_free(json);