{"record":{"id":"ec0c6d445ef5294d","repo":"netbirdio/netbird","slug":"set-network-layer-for-tcp-checksum-w","errorCode":null,"errorMessage":"set network layer for TCP checksum: %w","messagePattern":"set network layer for TCP checksum: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/firewall/uspfilter/tracer.go","lineNumber":187,"sourceCode":"\t\treturn nil, fmt.Errorf(\"unsupported protocol: %s\", p.Protocol)\n\t}\n}\n\nfunc (p *PacketBuilder) buildTCPLayer(ipLayer gopacket.SerializableLayer) ([]gopacket.SerializableLayer, error) {\n\ttcp := &layers.TCP{\n\t\tSrcPort: layers.TCPPort(p.SrcPort),\n\t\tDstPort: layers.TCPPort(p.DstPort),\n\t\tWindow:  65535,\n\t\tSYN:     p.TCPState != nil && p.TCPState.SYN,\n\t\tACK:     p.TCPState != nil && p.TCPState.ACK,\n\t\tFIN:     p.TCPState != nil && p.TCPState.FIN,\n\t\tRST:     p.TCPState != nil && p.TCPState.RST,\n\t\tPSH:     p.TCPState != nil && p.TCPState.PSH,\n\t\tURG:     p.TCPState != nil && p.TCPState.URG,\n\t}\n\tif nl, ok := ipLayer.(gopacket.NetworkLayer); ok {\n\t\tif err := tcp.SetNetworkLayerForChecksum(nl); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"set network layer for TCP checksum: %w\", err)\n\t\t}\n\t}\n\treturn []gopacket.SerializableLayer{tcp}, nil\n}\n\nfunc (p *PacketBuilder) buildUDPLayer(ipLayer gopacket.SerializableLayer) ([]gopacket.SerializableLayer, error) {\n\tudp := &layers.UDP{\n\t\tSrcPort: layers.UDPPort(p.SrcPort),\n\t\tDstPort: layers.UDPPort(p.DstPort),\n\t}\n\tif nl, ok := ipLayer.(gopacket.NetworkLayer); ok {\n\t\tif err := udp.SetNetworkLayerForChecksum(nl); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"set network layer for UDP checksum: %w\", err)\n\t\t}\n\t}\n\treturn []gopacket.SerializableLayer{udp}, nil\n}\n","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/firewall/uspfilter/tracer.go#L169-L205","documentation":"gopacket's TCP layer SetNetworkLayerForChecksum returns an error when the supplied network layer's address lengths do not match what the pseudo-header computation expects (a 4-byte expectation met with 16-byte addresses or vice versa). The tracer calls it so SerializeLayers with ComputeChecksums can build a correct TCP pseudo-header. In this code path the IP layer was just built from the same SrcIP/DstIP pair, so the guard in buildIPLayer normally prevents a family mismatch from reaching here; a hit indicates the layers were assembled inconsistently.","triggerScenarios":"Passing an IPv6 gopacket.NetworkLayer to a TCP layer whose addresses were populated from IPv4 data (or the reverse), typically only after refactoring buildIPLayer's output or reordering layer construction; also possible with a custom SerializableLayer masquerading as a NetworkLayer with wrong address sizes.","commonSituations":"Extending the tracer to support new protocols or tunneling and constructing the IP layer separately from the transport layer; version drift in gopacket changing what SetNetworkLayerForChecksum validates.","solutions":["Keep constructing the transport layer strictly from the ipLayer returned by buildIPLayer in the same call chain","Re-run the same-family validation from buildIPLayer (SrcIP.Is4() == DstIP.Is4()) before assembling layers","Pin and review the gopacket version after upgrades; the error text from gopacket names the size mismatch, which identifies the offending layer","Add a unit test that builds one TCP trace per family to catch regressions early"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// keep families consistent before building\nif b.SrcIP.Is4() != b.DstIP.Is4() {\n    return errors.New(\"refusing to build cross-family packet\")\n}","typeGuard":"func (p *PacketBuilder) layersConsistent() bool {\n    return p.SrcIP.IsValid() && p.DstIP.IsValid() && p.SrcIP.Is4() == p.DstIP.Is4()\n}","tryCatchPattern":"if _, err := b.Build(); err != nil {\n    if strings.Contains(err.Error(), \"checksum\") {\n        // layer pairing broke: rebuild from a fresh Build() call, never reuse layers\n    }\n    return err\n}","preventionTips":["Never assemble the TCP layer separately from the IP layer produced in the same Build","Lock gopacket version and re-run tracer tests on upgrade","Add TCP v4/v6 golden-packet tests so checksum regressions are caught in CI"],"tags":["go","netbird","gopacket","tcp","checksum","tracer"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}