summaryrefslogtreecommitdiff
path: root/proto/mrt/mrt.c
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2021-01-12 15:37:01 +0100
committerOndrej Zajicek (work) <santiago@crfreenet.org>2021-01-12 15:37:01 +0100
commitd774f6d721b0e52ed800c4b9a3a482c8ce9dd074 (patch)
tree8aa6798a9e775098edda40f348a6ee4646b64ee4 /proto/mrt/mrt.c
parent910adaa08bbd416288797505399ab47f990817e6 (diff)
MRT: Fix IPv6 table dumps
Add fake MP_REACH_NLRI attribute with BGP next hop when encoding MRT table dumps for IPv6 routes. That is necessary to encode next hop as NEXT_HOP attribute is not used for MP-BGP. Thanks to Santiago Aggio for the bugreport.
Diffstat (limited to 'proto/mrt/mrt.c')
-rw-r--r--proto/mrt/mrt.c64
1 files changed, 45 insertions, 19 deletions
diff --git a/proto/mrt/mrt.c b/proto/mrt/mrt.c
index 7a396a84..76d6c48f 100644
--- a/proto/mrt/mrt.c
+++ b/proto/mrt/mrt.c
@@ -417,6 +417,50 @@ mrt_rib_table_header(struct mrt_table_dump_state *s, net_addr *n)
mrt_put_u16(b, 0);
}
+#ifdef CONFIG_BGP
+static void
+mrt_rib_table_entry_bgp_attrs(struct mrt_table_dump_state *s, rte *r)
+{
+ struct ea_list *eattrs = r->attrs->eattrs;
+ buffer *b = &s->buf;
+
+ if (!eattrs)
+ return;
+
+ /* Attribute list must be normalized for bgp_encode_attrs() */
+ if (!rta_is_cached(r->attrs))
+ ea_normalize(eattrs);
+
+ mrt_buffer_need(b, MRT_ATTR_BUFFER_SIZE);
+ byte *pos = b->pos;
+
+ s->bws->mp_next_hop = NULL;
+
+ /* Encode BGP attributes */
+ int len = bgp_encode_attrs(s->bws, eattrs, pos, b->end);
+ if (len < 0)
+ goto fail;
+ pos += len;
+
+ /* Encode IPv6 next hop separately as fake MP_REACH_NLRI attribute */
+ if (s->bws->mp_next_hop)
+ {
+ len = bgp_encode_mp_reach_mrt(s->bws, s->bws->mp_next_hop, pos, b->end - pos);
+ if (len < 0)
+ goto fail;
+ pos += len;
+ }
+
+ /* Update attribute length and advance buffer pos */
+ put_u16(b->pos - 2, pos - b->pos);
+ b->pos = pos;
+ return;
+
+fail:
+ mrt_log(s, "Attribute list too long for %N", r->net->n.addr);
+}
+#endif
+
static void
mrt_rib_table_entry(struct mrt_table_dump_state *s, rte *r)
{
@@ -447,25 +491,7 @@ mrt_rib_table_entry(struct mrt_table_dump_state *s, rte *r)
mrt_put_u16(b, 0);
#ifdef CONFIG_BGP
- if (r->attrs->eattrs)
- {
- struct ea_list *eattrs = r->attrs->eattrs;
-
- if (!rta_is_cached(r->attrs))
- ea_normalize(eattrs);
-
- mrt_buffer_need(b, MRT_ATTR_BUFFER_SIZE);
- int alen = bgp_encode_attrs(s->bws, eattrs, b->pos, b->end);
-
- if (alen < 0)
- {
- mrt_log(s, "Attribute list too long for %N", r->net->n.addr);
- alen = 0;
- }
-
- put_u16(b->pos - 2, alen);
- b->pos += alen;
- }
+ mrt_rib_table_entry_bgp_attrs(s, r);
#endif
s->entry_count++;