bgpd: Remove the double-pass parsing of NLRIs
* bgpd parses NLRIs twice, a first pass "sanity check" and then a second pass
that changes actual state. For most AFI/SAFIs this is done by
bgp_nlri_sanity_check and bgp_nlri_parse, which are almost identical.
As the required action on a syntactic error in an NLRI is to NOTIFY and
shut down the session, it should be acceptable to just do a one pass
parse. There is no need to atomically handle the NLRIs.
* bgp_route.h: (bgp_nlri_sanity_check) Delete
* bgp_route.c: (bgp_nlri_parse) Make the prefixlen size check more general
and don't hard-code AFI/SAFI details, e.g. use prefix_blen library function.
Add error logs consistent with bgp_nlri_sanity_check as much as possible.
Add a "defense in depth" type check of the prefixlen against the sizeof
the (struct prefix) storage - ala bgp_nlri_parse_vpn.
Update standards text from draft RFC4271 to the actual RFC4271 text.
Extend the semantic consistency test of IPv6. E.g. it should skip mcast
NLRIs for unicast safi as v4 does.
* bgp_mplsvpn.{c,h}: Delete bgp_nlri_sanity_check_vpn and make
bgp_nlri_parse_vpn_body the bgp_nlri_parse_vpn function again.
(bgp_nlri_parse_vpn) Remove the notifies. The sanity checks were
responsible for this, but bgp_update_receive handles sending NOTIFY
generically for bgp_nlri_parse.
* bgp_attr.c: (bgp_mp_reach_parse,bgp_mp_unreach_parse) Delete sanity check.
NLRI parsing done after attr parsing by bgp_update_receive.
Arising out of discussions on the need for two-pass NLRI parse with:
Lou Berger <lberger@labn.net>
Donald Sharp <sharpd@cumulusnetworks.com>
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 83bb6ca..08a4272 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -93,9 +93,9 @@
rd_ip->val |= (u_int16_t) *pnt;
}
-static int
-bgp_nlri_parse_vpn_body (struct peer *peer, struct attr *attr,
- struct bgp_nlri *packet, bool update)
+int
+bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
+ struct bgp_nlri *packet)
{
u_char *pnt;
u_char *lim;
@@ -137,8 +137,6 @@
"%s [Error] Update packet error / VPNv4"
" (prefix length %d less than VPNv4 min length)",
peer->host, prefixlen);
- bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_OPT_ATTR_ERR);
return -1;
}
if ((pnt + psize) > lim)
@@ -148,8 +146,6 @@
" (psize %u exceeds packet size (%u)",
peer->host,
prefixlen, (uint)(lim-pnt));
- bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_OPT_ATTR_ERR);
return -1;
}
@@ -161,8 +157,6 @@
" (psize %u exceeds storage size (%zu)",
peer->host,
prefixlen - VPN_PREFIXLEN_MIN_BYTES*8, sizeof(p.u));
- bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_OPT_ATTR_ERR);
return -1;
}
@@ -175,8 +169,6 @@
peer->host,
prefixlen - VPN_PREFIXLEN_MIN_BYTES*8,
p.family, prefix_blen (&p));
- bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_OPT_ATTR_ERR);
return -1;
}
@@ -212,15 +204,12 @@
memcpy (&p.u.prefix, pnt + VPN_PREFIXLEN_MIN_BYTES,
psize - VPN_PREFIXLEN_MIN_BYTES);
- if (update)
- {
- if (attr)
- bgp_update (peer, &p, attr, packet->afi, SAFI_MPLS_VPN,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0);
- else
- bgp_withdraw (peer, &p, attr, packet->afi, SAFI_MPLS_VPN,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt);
- }
+ if (attr)
+ bgp_update (peer, &p, attr, packet->afi, SAFI_MPLS_VPN,
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0);
+ else
+ bgp_withdraw (peer, &p, attr, packet->afi, SAFI_MPLS_VPN,
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt);
}
/* Packet length consistency check. */
if (pnt != lim)
@@ -229,8 +218,6 @@
"%s [Error] Update packet error / VPNv4"
" (%zu data remaining after parsing)",
peer->host, lim - pnt);
- bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_OPT_ATTR_ERR);
return -1;
}
@@ -239,19 +226,6 @@
}
int
-bgp_nlri_sanity_check_vpn (struct peer *peer, struct bgp_nlri *nlri)
-{
- return bgp_nlri_parse_vpn_body (peer, NULL, nlri, false);
-}
-
-int
-bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
- struct bgp_nlri *packet)
-{
- return bgp_nlri_parse_vpn_body (peer, attr, packet, true);
-}
-
-int
str2prefix_rd (const char *str, struct prefix_rd *prd)
{
int ret; /* ret of called functions */