mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-13 10:14:50 +00:00
isisd: Add unpack function for SRv6 Locator TLV
Add a function to unpack an SRv6 Locator TLV and all its Sub-TLVs (RFC 9352 section #7.1). Signed-off-by: Carmine Scarpitta <carmine.scarpitta@uniroma2.it>
This commit is contained in:
parent
b2f0b7d0b0
commit
0225f908e8
@ -5625,6 +5625,103 @@ static int pack_item_srv6_locator(struct isis_item *i, struct stream *s,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unpack_item_srv6_locator(uint16_t mtid, uint8_t len,
|
||||
struct stream *s, struct sbuf *log,
|
||||
void *dest, int indent)
|
||||
{
|
||||
struct isis_tlvs *tlvs = dest;
|
||||
struct isis_srv6_locator_tlv *rv = NULL;
|
||||
size_t consume;
|
||||
uint8_t subtlv_len;
|
||||
struct isis_item_list *items;
|
||||
|
||||
items = isis_get_mt_items(&tlvs->srv6_locator, mtid);
|
||||
|
||||
sbuf_push(log, indent, "Unpacking SRv6 Locator...\n");
|
||||
consume = 7;
|
||||
if (len < consume) {
|
||||
sbuf_push(
|
||||
log, indent,
|
||||
"Not enough data left. (expected 7 or more bytes, got %hhu)\n",
|
||||
len);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
|
||||
|
||||
rv->metric = stream_getl(s);
|
||||
rv->flags = stream_getc(s);
|
||||
rv->algorithm = stream_getc(s);
|
||||
|
||||
rv->prefix.family = AF_INET6;
|
||||
rv->prefix.prefixlen = stream_getc(s);
|
||||
if (rv->prefix.prefixlen > IPV6_MAX_BITLEN) {
|
||||
sbuf_push(log, indent, "Loc Size %u is implausible for SRv6\n",
|
||||
rv->prefix.prefixlen);
|
||||
goto out;
|
||||
}
|
||||
|
||||
consume += PSIZE(rv->prefix.prefixlen);
|
||||
if (len < consume) {
|
||||
sbuf_push(
|
||||
log, indent,
|
||||
"Expected %u bytes of prefix, but only %u bytes available.\n",
|
||||
PSIZE(rv->prefix.prefixlen), len - 7);
|
||||
goto out;
|
||||
}
|
||||
stream_get(&rv->prefix.prefix.s6_addr, s, PSIZE(rv->prefix.prefixlen));
|
||||
|
||||
struct in6_addr orig_locator = rv->prefix.prefix;
|
||||
apply_mask_ipv6(&rv->prefix);
|
||||
if (memcmp(&orig_locator, &rv->prefix.prefix, sizeof(orig_locator)))
|
||||
sbuf_push(log, indent + 2,
|
||||
"WARNING: SRv6 Locator had hostbits set.\n");
|
||||
format_item_srv6_locator(mtid, (struct isis_item *)rv, log, NULL,
|
||||
indent + 2);
|
||||
|
||||
consume += 1;
|
||||
if (len < consume) {
|
||||
sbuf_push(
|
||||
log, indent,
|
||||
"Expected 1 byte of subtlv len, but no more data persent.\n");
|
||||
goto out;
|
||||
}
|
||||
subtlv_len = stream_getc(s);
|
||||
|
||||
if (subtlv_len) {
|
||||
consume += subtlv_len;
|
||||
if (len < consume) {
|
||||
sbuf_push(
|
||||
log, indent,
|
||||
"Expected %hhu bytes of subtlvs, but only %u bytes available.\n",
|
||||
subtlv_len,
|
||||
len - 7 - PSIZE(rv->prefix.prefixlen));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rv->subtlvs =
|
||||
isis_alloc_subtlvs(ISIS_CONTEXT_SUBTLV_SRV6_LOCATOR);
|
||||
|
||||
bool unpacked_known_tlvs = false;
|
||||
if (unpack_tlvs(ISIS_CONTEXT_SUBTLV_SRV6_LOCATOR, subtlv_len, s,
|
||||
log, rv->subtlvs, indent + 4,
|
||||
&unpacked_known_tlvs)) {
|
||||
goto out;
|
||||
}
|
||||
if (!unpacked_known_tlvs) {
|
||||
isis_free_subtlvs(rv->subtlvs);
|
||||
rv->subtlvs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
append_item(items, (struct isis_item *)rv);
|
||||
return 0;
|
||||
out:
|
||||
if (rv)
|
||||
free_item_srv6_locator((struct isis_item *)rv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Functions related to tlvs in general */
|
||||
|
||||
struct isis_tlvs *isis_alloc_tlvs(void)
|
||||
|
Loading…
Reference in New Issue
Block a user