diff options
-rw-r--r-- | bgpd/bgp_attr.c | 42 | ||||
-rw-r--r-- | bgpd/bgp_attr.h | 7 | ||||
-rw-r--r-- | tests/bgp_mp_attr_test.c | 4 |
3 files changed, 42 insertions, 11 deletions
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 */ diff --git a/tests/bgp_mp_attr_test.c b/tests/bgp_mp_attr_test.c index d6e9f0ce..9cbe9f22 100644 --- a/tests/bgp_mp_attr_test.c +++ b/tests/bgp_mp_attr_test.c @@ -449,9 +449,9 @@ parse_test (struct peer *peer, struct test_segment *t, int type) printf ("%s: %s\n", t->name, t->desc); if (type == BGP_ATTR_MP_REACH_NLRI) - ret = bgp_mp_reach_parse (peer, t->len, &attr, &nlri); + ret = bgp_mp_reach_parse (peer, t->len, &attr, BGP_ATTR_FLAG_OPTIONAL, BGP_INPUT_PNT (peer), &nlri); else - ret = bgp_mp_unreach_parse (peer, t->len, &nlri); + ret = bgp_mp_unreach_parse (peer, t->len, BGP_ATTR_FLAG_OPTIONAL, BGP_INPUT_PNT (peer), &nlri); if (!ret) { |