From: Igor Putovny Date: Fri, 1 Aug 2025 12:04:23 +0000 (+0200) Subject: Validate vxlan attributes before protocol starts X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2Fip-evpn;p=thirdparty%2Fbird.git Validate vxlan attributes before protocol starts --- diff --git a/proto/evpn/evpn.c b/proto/evpn/evpn.c index a4c2cdbab..5f84c12a1 100644 --- a/proto/evpn/evpn.c +++ b/proto/evpn/evpn.c @@ -55,6 +55,7 @@ #include "filter/filter.h" #include "filter/data.h" #include "lib/string.h" +#include "sysdep/unix/krt.h" #include "evpn.h" @@ -424,9 +425,70 @@ evpn_rt_notify(struct proto *P, struct channel *c0 UNUSED, net *net, rte *new, r } } +static int +evpn_validate_iface_attrs(struct evpn_proto *p, const struct iface *i) +{ + if (!i->attrs || !i->attrs->eattrs) + return 0; + + struct evpn_encap *encap = evpn_get_encap(p); + + if (encap->tunnel_dev != i) + return 0; + + const struct adata *addr = ea_get_adata(i->attrs->eattrs, EA_IFACE_VXLAN_IP_ADDR); + + u32 type = ea_get_int(i->attrs->eattrs, EA_IFACE_VXLAN_TYPE, (u32)-1); + u32 if_vni = ea_get_int(i->attrs->eattrs, EA_IFACE_VXLAN_ID, EVPN_VNI_NOT_SET); + + if (type != IFACE_TYPE_VXLAN || addr == &null_adata) + return 0; + + ip_addr if_addr; + ASSERT(sizeof(if_addr) == addr->length); + memcpy(&if_addr, addr->data, addr->length); + + struct evpn_config *cf = SKIP_BACK(struct evpn_config, c, p->p.cf); + + if (cf->vni != EVPN_VNI_NOT_SET && if_vni != EVPN_VNI_NOT_SET && cf->vni != if_vni) + { + log(L_ERR "%s: VNI mismatch", p->p.name); + return 0; + } + + if (cf->vni == EVPN_VNI_NOT_SET && if_vni != EVPN_VNI_NOT_SET) + p->vni = if_vni; + + if (cf->vni == EVPN_VNI_NOT_SET && if_vni == EVPN_VNI_NOT_SET) + { + log(L_ERR "%s: Unknown VNI", p->p.name); + return 0; + } + + if (ipa_zero(encap->router_addr) && ipa_zero(if_addr)) + { + log(L_ERR "%s: Unknown router IP", p->p.name); + return 0; + } + + if (!ipa_zero(encap->router_addr) && !ipa_zero(if_addr) && !ipa_equal(encap->router_addr, if_addr)) + { + log(L_ERR "%s: Router IP mismatch", p->p.name); + return 0; + } + + if (ipa_zero(encap->router_addr) && !ipa_zero(if_addr)) + encap->router_addr = if_addr; + + return 1; +} + static void -evpn_started(struct evpn_proto *p) +evpn_started(struct evpn_proto *p, const struct iface *i) { + if (!evpn_validate_iface_attrs(p, i)) + return; + proto_notify_state(&p->p, PS_UP); evpn_announce_imet(p, EVPN_ROOT_VLAN(p), 1); @@ -451,7 +513,7 @@ evpn_if_notify(struct proto *P, unsigned flags, struct iface *iface) return; if (flags & IF_CHANGE_UP) - evpn_started(p); + evpn_started(p, iface); else if (flags & IF_CHANGE_DOWN) proto_notify_state(&p->p, PS_STOP); }