slackhq/nebula · error
header len %d exceeds max %d
Error message
header len %d exceeds max %d
What it means
SegmentTCP stamps a copy of the L3+L4 headers in front of every segment. maxSegHdrLen caps how large that per-segment header can be (worst case IPv4/IPv6 plus options plus TCP options). If the caller-supplied hdrLenU exceeds this cap the function refuses rather than write out-of-bounds or misaligned headers.
Source
Thrown at overlay/tio/virtio/segment_linux.go:225
return sum
}
// SegmentTCP walks a TSO superpacket pkt, yielding each segment as a slice into pkt.
// Per-segment plaintext is laid out by stamping a copy of the original L3+L4 header into pkt at offset i*gsoSize,
// where it sits immediately before that segment's payload chunk in the original buffer.
// pkt is consumed by this call and must not be inspected by the caller after the final yield.
func SegmentTCP(pkt []byte, hdrLenU, csumStartU, gsoSizeU uint16, yield func(seg []byte) error) error {
if gsoSizeU == 0 {
return fmt.Errorf("gso_size is zero")
}
if csumStartU == 0 {
return fmt.Errorf("csum_start is zero")
}
headerLen := int(hdrLenU)
csumStart := int(csumStartU)
if headerLen > maxSegHdrLen {
return fmt.Errorf("header len %d exceeds max %d", headerLen, maxSegHdrLen)
}
isV4 := pkt[0]>>4 == 4
tcpHdrLen := int(pkt[csumStart+tcpDataOffOff]>>4) * 4
payLen := len(pkt) - headerLen
gsoSize := int(gsoSizeU)
numSeg := segCount(payLen, gsoSize)
origSeq := binary.BigEndian.Uint32(pkt[csumStart+tcpSeqOff : csumStart+tcpSeqOff+4])
origFlags := pkt[csumStart+tcpFlagsOff]
baseProtoSum := basePseudoSum(pkt, isV4, unix.IPPROTO_TCP)
baseTcpHdrSum := baseTCPHdrSum(pkt, csumStart, headerLen)
var origIPID uint16
var baseIPHdrSum uint32
if isV4 {
origIPID = binary.BigEndian.Uint16(pkt[ipv4IDOff : ipv4IDOff+2])View on GitHub (pinned to dd8f660c0a)
Solutions
- Pass hdrLenU as the exact L3 header length + TCP header length (csumStart + TCP data offset), not the whole packet length.
- Sanity-check hdrLen <= 128 (or the library's maxSegHdrLen) before calling; drop the packet if exceeded as malformed.
- Verify IPv4 IHL and TCP data-offset nibbles are within 4..15 when you compute them, otherwise discard the frame upstream.
- Confirm you are not double-counting link-layer bytes in hdrLen.
Example fix
// before
hdrLen := uint16(len(pkt)) // wrong: whole packet
seg.SegmentTCP(pkt, hdrLen, csumStart, gsoSize, yield)
// after
tcpHdrLen := int(pkt[csumStart+tcpDataOffOff]>>4) * 4
hdrLen := uint16(csumStart + tcpHdrLen)
if hdrLen > seg.MaxSegHdrLen { return errors.New("header too large") }
seg.SegmentTCP(pkt, hdrLen, csumStart, gsoSize, yield) Defensive patterns
Strategy: validation
Validate before calling
tcpHdrLen := int(pkt[csumStart+12]>>4) * 4
hdrLen := uint16(csumStart + tcpHdrLen)
if hdrLen > 128 { // maxSegHdrLen
return fmt.Errorf("implausible header length %d; dropping", hdrLen)
}
segmenter.SegmentTCP(pkt, hdrLen, csumStart, gsoSize, yield) Type guard
func plausibleHdrLen(hdrLen uint16) bool { return hdrLen >= 40 && hdrLen <= 128 } Try / catch
err := segmenter.SegmentTCP(pkt, hdrLen, csumStart, gsoSize, yield)
if err != nil {
if strings.Contains(err.Error(), "exceeds max") {
log.Warn("oversized segment header; dropping malformed frame")
return nil
}
return err
} Prevention
- Compute hdrLen as L3 header length + TCP data-offset length, never as the packet length.
- Clamp and sanity-check IP IHL and TCP data-offset nibbles (<= 15) during header parsing.
- Don't include link-layer or VLAN bytes in hdrLen unless the library expects them.
- Treat oversized hdrLen as evidence of corruption and drop the frame upstream.
When it happens
Trigger: Calling SegmentTCP with hdrLenU > maxSegHdrLen — e.g. hdrLen was computed from a corrupted header stack, includes payload bytes, or the caller passed len(pkt) instead of the header length.
Common situations: Malformed packets with pathological IP option chains; a parsing bug that added the payload length into hdrLen; confusion between hdrLen (L3+L4) and csumStart (L4 offset) values when wiring up the call; raw-captured frames with garbage after the link layer.
Related errors
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/2126dfe85a44a98f.
Report an issue: GitHub.