From 565b828dc00cafd477dd69ce15f0f551ece67710 Mon Sep 17 00:00:00 2001 From: Denis Ovsienko Date: Mon, 10 Oct 2011 21:08:33 +0400 Subject: bgpd: add flag checks for MP_(UN)REACH_NLRI * bgp_attr.[ch] * bgp_mp_reach_parse(): add extra arguments and a uniform flag check block * bgp_mp_unreach_parse(): idem * bgp_attr_parse(): provide extra arguments * bgp_mp_attr_test.c * parse_test(): justify respective calls --- bgpd/bgp_attr.c | 42 ++++++++++++++++++++++++++++++++++++------ bgpd/bgp_attr.h | 7 ++++--- 2 files changed, 40 insertions(+), 9 deletions(-) (limited to 'bgpd') diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 8a85fc22..c2e5fede 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -1431,8 +1431,8 @@ bgp_attr_cluster_list (struct peer *peer, bgp_size_t length, /* Multiprotocol reachability information parse. */ int -bgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr, - struct bgp_nlri *mp_update) +bgp_mp_reach_parse (struct peer *peer, const bgp_size_t length, + struct attr *attr, const u_char flag, u_char *startp, struct bgp_nlri *mp_update) { afi_t afi; safi_t safi; @@ -1441,7 +1441,21 @@ bgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr, int ret; struct stream *s; struct attr_extra *attre = bgp_attr_extra_get(attr); - + bgp_size_t total; + + total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3); + /* Flag checks. */ + if (flag != BGP_ATTR_FLAG_OPTIONAL) + { + if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL)) + zlog (peer->log, LOG_ERR, "MP_REACH_NLRI attribute must be flagged as \"optional\" (%u)", flag); + if (CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS)) + zlog (peer->log, LOG_ERR, "MP_REACH_NLRI attribute must not be flagged as \"transitive\" (%u)", flag); + if (CHECK_FLAG (flag, BGP_ATTR_FLAG_PARTIAL)) + zlog (peer->log, LOG_ERR, "MP_REACH_NLRI attribute must not be flagged as \"partial\" (%u)", flag); + bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total); + return -1; + } /* Set end of packet. */ s = BGP_INPUT(peer); start = stream_get_getp(s); @@ -1565,7 +1579,8 @@ bgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr, /* Multiprotocol unreachable parse */ int -bgp_mp_unreach_parse (struct peer *peer, bgp_size_t length, +bgp_mp_unreach_parse (struct peer *peer, const bgp_size_t length, + const u_char flag, u_char *startp, struct bgp_nlri *mp_withdraw) { struct stream *s; @@ -1573,6 +1588,21 @@ bgp_mp_unreach_parse (struct peer *peer, bgp_size_t length, safi_t safi; u_int16_t withdraw_len; int ret; + bgp_size_t total; + + total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3); + /* Flag checks. */ + if (flag != BGP_ATTR_FLAG_OPTIONAL) + { + if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL)) + zlog (peer->log, LOG_ERR, "MP_UNREACH_NLRI attribute must be flagged as \"optional\" (%u)", flag); + if (CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS)) + zlog (peer->log, LOG_ERR, "MP_UNREACH_NLRI attribute must not be flagged as \"transitive\" (%u)", flag); + if (CHECK_FLAG (flag, BGP_ATTR_FLAG_PARTIAL)) + zlog (peer->log, LOG_ERR, "MP_UNREACH_NLRI attribute must not be flagged as \"partial\" (%u)", flag); + bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, startp, total); + return -1; + } s = peer->ibuf; @@ -1844,10 +1874,10 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, ret = bgp_attr_cluster_list (peer, length, attr, flag, startp); break; case BGP_ATTR_MP_REACH_NLRI: - ret = bgp_mp_reach_parse (peer, length, attr, mp_update); + ret = bgp_mp_reach_parse (peer, length, attr, flag, startp, mp_update); break; case BGP_ATTR_MP_UNREACH_NLRI: - ret = bgp_mp_unreach_parse (peer, length, mp_withdraw); + ret = bgp_mp_unreach_parse (peer, length, flag, startp, mp_withdraw); break; case BGP_ATTR_EXT_COMMUNITIES: ret = bgp_attr_ext_communities (peer, length, attr, flag, startp); diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index c0112514..e6300740 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -180,8 +180,9 @@ extern void cluster_unintern (struct cluster_list *); void transit_unintern (struct transit *); /* Exported for unit-test purposes only */ -extern int bgp_mp_reach_parse (struct peer *, bgp_size_t, struct attr *, - struct bgp_nlri *); -extern int bgp_mp_unreach_parse (struct peer *, bgp_size_t, struct bgp_nlri *); +extern int bgp_mp_reach_parse (struct peer *, const bgp_size_t, struct attr *, + const u_char, u_char *, struct bgp_nlri *); +extern int bgp_mp_unreach_parse (struct peer *, const bgp_size_t, const u_char, + u_char *, struct bgp_nlri *); #endif /* _QUAGGA_BGP_ATTR_H */ -- cgit v1.2.1