diff options
Diffstat (limited to 'proto/ospf/lsalib.c')
-rw-r--r-- | proto/ospf/lsalib.c | 95 |
1 files changed, 85 insertions, 10 deletions
diff --git a/proto/ospf/lsalib.c b/proto/ospf/lsalib.c index fbfd8d29..e66d3dc0 100644 --- a/proto/ospf/lsalib.c +++ b/proto/ospf/lsalib.c @@ -91,6 +91,30 @@ lsa_flooding_allowed(u32 type, u32 domain, struct ospf_iface *ifa) } } +int +lsa_is_acceptable(u32 type, struct ospf_neighbor *n, struct ospf_proto *p) +{ + if (ospf_is_v2(p)) + { + if (type == LSA_T_NSSA) + return !!(n->options & OPT_N); + + if (lsa_is_opaque(type)) + return !!(n->options & OPT_O); + + return 1; + } + else + { + /* + * There should be check whether receiving router understands that type + * of LSA (for LSA types with U-bit == 0). But as we do not support any + * optional LSA types, this is not needed yet. + */ + + return 1; + } +} static int unknown_lsa_type(u32 type) @@ -105,6 +129,9 @@ unknown_lsa_type(u32 type) case LSA_T_NSSA: case LSA_T_LINK: case LSA_T_PREFIX: + case LSA_T_RI_LINK: + case LSA_T_RI_AREA: + case LSA_T_RI_AS: return 0; default: @@ -112,28 +139,47 @@ unknown_lsa_type(u32 type) } } -#define LSA_V2_TMAX 8 -static const u16 lsa_v2_types[LSA_V2_TMAX] = - {0, LSA_T_RT, LSA_T_NET, LSA_T_SUM_NET, LSA_T_SUM_RT, LSA_T_EXT, 0, LSA_T_NSSA}; +/* Maps OSPFv2 types to OSPFv3 types */ +static const u16 lsa_v2_types[] = { + 0, LSA_T_RT, LSA_T_NET, LSA_T_SUM_NET, LSA_T_SUM_RT, LSA_T_EXT, 0, LSA_T_NSSA, + 0, LSA_T_OPAQUE_LINK, LSA_T_OPAQUE_AREA, LSA_T_OPAQUE_AS +}; + +/* Maps OSPFv2 opaque types to OSPFv3 function codes */ +static const u16 opaque_lsa_types[] = { + [LSA_OT_RI] = LSA_T_RI_, +}; + +/* Maps (subset of) OSPFv3 function codes to OSPFv2 opaque types */ +static const u8 opaque_lsa_types_inv[] = { + [LSA_T_RI_] = LSA_OT_RI, +}; + +#define LOOKUP(a, i) ({ uint _i = (i); (_i < ARRAY_SIZE(a)) ? a[_i] : 0; }) void -lsa_get_type_domain_(u32 itype, struct ospf_iface *ifa, u32 *otype, u32 *domain) +lsa_get_type_domain_(u32 type, u32 id, struct ospf_iface *ifa, u32 *otype, u32 *domain) { if (ospf_is_v2(ifa->oa->po)) { - itype = itype & LSA_T_V2_MASK; - itype = (itype < LSA_V2_TMAX) ? lsa_v2_types[itype] : 0; + type = type & LSA_T_V2_MASK; + type = LOOKUP(lsa_v2_types, type); + + uint code; + if (LSA_FUNCTION(type) == LSA_T_OPAQUE_) + if (code = LOOKUP(opaque_lsa_types, id >> 24)) + type = code | LSA_UBIT | LSA_SCOPE(type); } else { /* For unkown LSAs without U-bit change scope to LSA_SCOPE_LINK */ - if (unknown_lsa_type(itype) && !(itype & LSA_UBIT)) - itype = itype & ~LSA_SCOPE_MASK; + if (unknown_lsa_type(type) && !(type & LSA_UBIT)) + type = type & ~LSA_SCOPE_MASK; } - *otype = itype; + *otype = type; - switch (LSA_SCOPE(itype)) + switch (LSA_SCOPE(type)) { case LSA_SCOPE_LINK: *domain = ifa->iface_id; @@ -150,6 +196,12 @@ lsa_get_type_domain_(u32 itype, struct ospf_iface *ifa, u32 *otype, u32 *domain) } } +u32 +lsa_get_opaque_type(u32 type) +{ + return LOOKUP(opaque_lsa_types_inv, LSA_FUNCTION(type)); +} + void lsa_generate_checksum(struct ospf_lsa_header *lsa, const u8 *body) @@ -548,6 +600,17 @@ lsa_validate_prefix(struct ospf_lsa_header *lsa, struct ospf_lsa_prefix *body) return lsa_validate_pxlist(lsa, body->pxcount, sizeof(struct ospf_lsa_prefix), (u8 *) body); } +static int +lsa_validate_ri(struct ospf_lsa_header *lsa UNUSED, struct ospf_lsa_net *body UNUSED) +{ + /* + * There should be proper validation. But we do not really process RI LSAs, so + * we can just accept them like another unknown opaque LSAs. + */ + + return 1; +} + /** * lsa_validate - check whether given LSA is valid @@ -577,6 +640,14 @@ lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, void *body) case LSA_T_EXT: case LSA_T_NSSA: return lsa_validate_ext2(lsa, body); + case LSA_T_RI_LINK: + case LSA_T_RI_AREA: + case LSA_T_RI_AS: + return lsa_validate_ri(lsa, body); + case LSA_T_OPAQUE_LINK: + case LSA_T_OPAQUE_AREA: + case LSA_T_OPAQUE_AS: + return 1; /* Unknown Opaque LSAs */ default: return 0; /* Should not happen, unknown LSAs are already rejected */ } @@ -600,6 +671,10 @@ lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, void *body) return lsa_validate_link(lsa, body); case LSA_T_PREFIX: return lsa_validate_prefix(lsa, body); + case LSA_T_RI_LINK: + case LSA_T_RI_AREA: + case LSA_T_RI_AS: + return lsa_validate_ri(lsa, body); default: return 1; /* Unknown LSAs are OK in OSPFv3 */ } |