SRv6

Segments and TLVs, safely.

BufferView::srv6_header() returns an SRH only when the IPv6 Next Header is Routing (43), the SRH is the first extension header, and routing_type == 4.

Bounds-checked walk

Use validate_srh_bounds, safe_segment_at and safe_tlv_region when parsing untrusted packets.

srv6_safe.cxx
#include "vbvx/buffer_view.hxx"

vbvx::BufferView buf(packet_data, packet_len);

if (auto srh = buf.srv6_header()) {
  const uint16_t remaining = static_cast<uint16_t>(
    packet_len - (buf.l3_offset() + sizeof(vbvx::IPv6Header)));

  if (srh->validate_srh_bounds(remaining)) {
    auto n = srh->segments_count();

    if (auto first = srh->safe_segment_at(0, remaining)) {
      // first->data() / first->size()
    }

    if (auto tlvs = srh->safe_tlv_region(remaining)) {
      vbvx::SRv6TlvIterator it(tlvs->data(),
                               static_cast<uint16_t>(tlvs->size()));
      vbvx::SRv6Tlv t;
      while (it.next(t)) {
        // handle t.type, t.length, t.value
      }
    }
  }
}

Unchecked fast-path

For trusted provenance, iterate TLVs directly with tlv_first_ptr() and tlv_bytes_len().

srv6_fast.cxx
if (auto srh = buf.srv6_header()) {
  vbvx::SRv6TlvIterator it(srh->tlv_first_ptr(),
                           srh->tlv_bytes_len());
  vbvx::SRv6Tlv t;
  while (it.next(t)) {
    // handle t
  }
}

Where it lives

  • vbvx/srv6_header.hxx
  • tests/test_srv6_header.cxx
  • tests/test_srv6_tlv.cxx