Skip to content

[client] Add non-root ICMP support to userspace firewall forwarder#4792

Merged
lixmal merged 18 commits intomainfrom
forwarder-ping
Jan 8, 2026
Merged

[client] Add non-root ICMP support to userspace firewall forwarder#4792
lixmal merged 18 commits intomainfrom
forwarder-ping

Conversation

@lixmal
Copy link
Copy Markdown
Collaborator

@lixmal lixmal commented Nov 15, 2025

Describe your changes

  • Use the ping binary if we cannot create raw sockets
  • Bump gvisor/netstack to fix duplicate echo replies (this also bumps the min Go version)
  • Bump wireguard-go fork to work with the new gvisor
  • Adjust forwarder to work with new netstack code
  • Adjust ice_bind to work with new wireguard-go code
  • Fix a bug where waiting for echo replies would block all other packets

Depends on netbirdio/wireguard-go#12

Issue ticket number and link

Stack

Checklist

  • Is it a bug fix
  • Is a typo/documentation fix
  • Is a feature enhancement
  • It is a refactor
  • Created tests that fail without the change (if possible)

By submitting this pull request, you confirm that you have read and agree to the terms of the Contributor License Agreement.

Documentation

Select exactly one:

  • I added/updated documentation for this change
  • Documentation is not needed for this change (explain why)

Docs PR URL (required if "docs added" is checked)

Paste the PR link from https://github.com/netbirdio/docs here:

https://github.com/netbirdio/docs/pull/__

Summary by CodeRabbit

  • New Features

    • Asynchronous ICMP echo handling with startup raw-socket capability detection, rate-limited system-ping fallback, and synthesized echo replies.
    • UDP handling now reports explicit success/failure outcomes.
    • Receiver creation broadened to support non-IPv4 batch readers.
    • Added an extended warn-level logging helper.
  • Bug Fixes / Stability

    • MTU access made atomic to reduce races and improve stability.
  • Chores

    • Bumped several core dependencies and module replacements.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Nov 15, 2025

📝 Walkthrough

Walkthrough

Adds atomic MTU and lifecycle stubs to endpoint; probes raw ICMP capability and implements async ICMP Echo handling with raw-socket and system-ping fallbacks; changes UDP handler to return bool; generalizes ICE receiver to accept batch readers; adds Warn4 logger and updates module dependencies.

Changes

Cohort / File(s) Summary
Endpoint lifecycle & atomicity
client/firewall/uspfilter/forwarder/endpoint.go
mtu changed from uint32atomic.Uint32; MTU() uses Load(); added Close(), SetLinkAddress(), SetMTU(uint32), SetOnCloseAction(func()) (mostly stubs; SetMTU stores atomically).
Forwarder init & ICMP capability
client/firewall/uspfilter/forwarder/forwarder.go
Forwarder adds hasRawICMPAccess bool and pingSemaphore chan struct{}; endpoint MTU initialized; checkICMPCapability() probes raw ICMP access at startup and logs fallback.
ICMP handling & ping fallback
client/firewall/uspfilter/forwarder/icmp.go
Major refactor: handleICMP now takes *stack.PacketBuffer; adds async handleICMPEcho with semaphore rate-limiting; raw-socket path (forwardICMPPacket, handleICMPViaSocket) and ping fallback (handleICMPViaPing, buildPingCommand); adds synthesizeEchoReply, injectICMPReply, RTT measurement, and PacketConn-based response handling.
UDP handler return semantics
client/firewall/uspfilter/forwarder/udp.go
handleUDP(...) signature changed to bool; return paths updated for errors/context cancellation; gonet.NewUDPConn call adjusted; isClosedError treats io.EOF as closed.
Logging API
client/firewall/uspfilter/log/log.go
Added Warn4(format string, arg1, arg2, arg3, arg4 any) mirroring Warn3, non-blocking enqueue for LevelWarn.
Receiver creation generalization
client/iface/bind/ice_bind.go
Replaced IPv4-specific factory with CreateReceiverFn(pc wgConn.BatchReader, ...); createIPv4ReceiverFn now accepts wgConn.BatchReader and provides IPv4-specific or generic fallback behavior (stub for non-IPv4).
Dependency updates
go.mod
Module bumps and replaces: gvisor, creack/pty, wireguard replacement, pion/ice replacement, go-netroute replacement, dex replacement.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Client
    participant Forwarder
    participant ICMP as ICMPHandler
    participant Raw as RawSocket
    participant Ping as PingCmd
    participant Stack as Netstack

    Client->>Forwarder: inbound IP packet (ICMP Echo request)
    Forwarder->>ICMP: handleICMP(id, pkt)
    ICMP->>ICMP: handleICMPEcho(flowID, id, pkt) (async, semaphore)
    alt Forwarder.hasRawICMPAccess == true
        ICMP->>Raw: forwardICMPPacket / handleICMPViaSocket
        Raw->>Raw: open raw socket, send packet, receive reply
        Raw->>ICMP: handleEchoResponse(conn)
        ICMP->>Stack: injectICMPReply
    else
        ICMP->>Ping: handleICMPViaPing (build & run ping)
        Ping->>Ping: execute system ping, capture RTT
        Ping->>ICMP: synthesizeEchoReply
        ICMP->>Stack: injectICMPReply
    end
    Stack-->>Client: ICMP reply delivered
Loading
sequenceDiagram
    autonumber
    participant Caller
    participant UDP as UDPHandler
    participant Endpoint
    participant Proxy

    Caller->>UDP: handleUDP(request)
    alt ctx cancelled
        UDP-->>Caller: return false
    else
        UDP->>Endpoint: SetMTU (atomic.Store)
        UDP->>UDP: create gonet.NewUDPConn(...)
        alt conn created
            UDP-->>Caller: return true
            UDP->>Proxy: spawn proxy goroutine
        else
            UDP-->>Caller: return false
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • pappz
  • crn4
  • mlsmaycon

Poem

🐰 I stash the MTU with atomic care,

Echoes race through socket or pinging air,
A semaphore hushes eager hops,
UDP answers true or false on stops,
The rabbit cheers the forwarder's new flair!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding non-root ICMP support to the userspace firewall forwarder via ping binary fallback.
Description check ✅ Passed The description covers the key changes, dependencies, and documentation status. All required template sections are addressed with appropriate content.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a8b3dc1 and 64dbfdf.

📒 Files selected for processing (1)
  • client/iface/bind/ice_bind.go
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4792
File: client/firewall/uspfilter/forwarder/icmp.go:32-48
Timestamp: 2025-11-16T19:27:08.018Z
Learning: In the netbird userspace firewall forwarder (client/firewall/uspfilter/forwarder/), flow events (TypeStart/TypeEnd) are only sent for ICMP echo requests/replies to track the complete bidirectional flow. Other ICMP types (Time Exceeded, Destination Unreachable, etc.) only get a TypeStart event without a corresponding TypeEnd event, as they are typically one-way notifications that don't require complete lifecycle tracking.
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4792
File: client/firewall/uspfilter/forwarder/icmp.go:32-48
Timestamp: 2025-11-15T14:46:06.743Z
Learning: In the netbird userspace firewall forwarder (client/firewall/uspfilter/forwarder/), the boolean return value from ICMP/UDP handlers indicates packet ownership to netstack: `true` means "I handled this packet, don't process it further" and `false` means "I didn't handle it, netstack should handle it". This is used to prevent netstack from generating its own replies even when forwarding fails.
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4792
File: client/iface/bind/ice_bind.go:34-44
Timestamp: 2026-01-08T16:23:05.027Z
Learning: In client/iface/bind/ice_bind.go, the fallback receiver path in CreateReceiverFn (lines 34-44) is intentionally a minimal stub to maintain interface compatibility with the wireguard-go fork. It does not include STUN filtering, activity recording, or UDP mux initialization because IPv6 is not yet supported in the udpmux, and this path primarily handles non-IPv4 PacketConn cases that aren't fully supported yet.
📚 Learning: 2026-01-08T16:23:05.027Z
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4792
File: client/iface/bind/ice_bind.go:34-44
Timestamp: 2026-01-08T16:23:05.027Z
Learning: In client/iface/bind/ice_bind.go, the fallback receiver path in CreateReceiverFn (lines 34-44) is intentionally a minimal stub to maintain interface compatibility with the wireguard-go fork. It does not include STUN filtering, activity recording, or UDP mux initialization because IPv6 is not yet supported in the udpmux, and this path primarily handles non-IPv4 PacketConn cases that aren't fully supported yet.

Applied to files:

  • client/iface/bind/ice_bind.go
📚 Learning: 2025-11-15T14:46:06.743Z
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4792
File: client/firewall/uspfilter/forwarder/icmp.go:32-48
Timestamp: 2025-11-15T14:46:06.743Z
Learning: In the netbird userspace firewall forwarder (client/firewall/uspfilter/forwarder/), the boolean return value from ICMP/UDP handlers indicates packet ownership to netstack: `true` means "I handled this packet, don't process it further" and `false` means "I didn't handle it, netstack should handle it". This is used to prevent netstack from generating its own replies even when forwarding fails.

Applied to files:

  • client/iface/bind/ice_bind.go
📚 Learning: 2025-11-13T15:19:32.799Z
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4777
File: client/firewall/iptables/acl_linux.go:439-450
Timestamp: 2025-11-13T15:19:32.799Z
Learning: In the netbird client firewall iptables implementation (client/firewall/iptables/), IPv6 is not currently handled or supported.

Applied to files:

  • client/iface/bind/ice_bind.go
📚 Learning: 2025-11-16T19:27:08.018Z
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4792
File: client/firewall/uspfilter/forwarder/icmp.go:32-48
Timestamp: 2025-11-16T19:27:08.018Z
Learning: In the netbird userspace firewall forwarder (client/firewall/uspfilter/forwarder/), flow events (TypeStart/TypeEnd) are only sent for ICMP echo requests/replies to track the complete bidirectional flow. Other ICMP types (Time Exceeded, Destination Unreachable, etc.) only get a TypeStart event without a corresponding TypeEnd event, as they are typically one-way notifications that don't require complete lifecycle tracking.

Applied to files:

  • client/iface/bind/ice_bind.go
🧬 Code graph analysis (1)
client/iface/bind/ice_bind.go (3)
client/net/listener_listen.go (2)
  • UDPConn (58-62)
  • PacketConn (37-41)
client/iface/udpmux/universal.go (1)
  • UDPConn (119-127)
client/iface/bind/endpoint.go (1)
  • Endpoint (9-9)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (24)
  • GitHub Check: Signal / Unit (386)
  • GitHub Check: Signal / Unit (amd64)
  • GitHub Check: Management / Unit (amd64, postgres)
  • GitHub Check: Management / Unit (amd64, sqlite)
  • GitHub Check: Relay / Unit (386)
  • GitHub Check: Client / Unit (amd64)
  • GitHub Check: Client / Unit (386)
  • GitHub Check: Management / Unit (amd64, mysql)
  • GitHub Check: Relay / Unit (amd64, -race)
  • GitHub Check: Client (Docker) / Unit
  • GitHub Check: Client / Unit
  • GitHub Check: Android / Build
  • GitHub Check: Client / Unit
  • GitHub Check: release
  • GitHub Check: JS / Lint
  • GitHub Check: FreeBSD Port / Build & Test
  • GitHub Check: release_ui_darwin
  • GitHub Check: release_ui
  • GitHub Check: iOS / Build
  • GitHub Check: Client / Unit
  • GitHub Check: Darwin
  • GitHub Check: Linux
  • GitHub Check: Windows
  • GitHub Check: Check External GPL/AGPL Licenses
🔇 Additional comments (1)
client/iface/bind/ice_bind.go (1)

30-47: Adapter correctly generalizes to BatchReader interface.

The refactoring from CreateIPv4ReceiverFn to CreateReceiverFn properly adapts to the updated wireguard-go fork. The type assertion cleanly separates the IPv4 path (with full STUN filtering and mux support) from the IPv6 fallback, which is intentionally a minimal stub since IPv6 is not yet supported in the udpmux.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
client/firewall/uspfilter/forwarder/icmp.go (1)

57-65: Consider adding panic recovery to the goroutine.

If handleICMPViaSocket or handleICMPViaPing panic, the goroutine will crash silently. Consider adding a deferred panic recovery handler to log any unexpected panics.

Apply this diff to add panic recovery:

 		go func() {
 			defer func() { <-f.pingSemaphore }()
+			defer func() {
+				if r := recover(); r != nil {
+					f.logger.Error1("forwarder: Panic in ICMP echo handler: %v", r)
+				}
+			}()
 
 			if f.hasRawICMPAccess {
 				f.handleICMPViaSocket(flowID, id, icmpHdr, icmpData, rxBytes)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7d5cdc and 099870d.

📒 Files selected for processing (1)
  • client/firewall/uspfilter/forwarder/icmp.go (4 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4777
File: client/firewall/iptables/acl_linux.go:439-450
Timestamp: 2025-11-13T15:19:32.799Z
Learning: In the netbird client firewall iptables implementation (client/firewall/iptables/), IPv6 is not currently handled or supported.
🧬 Code graph analysis (1)
client/firewall/uspfilter/forwarder/icmp.go (1)
client/firewall/uspfilter/forwarder/forwarder.go (2)
  • Forwarder (35-49)
  • New (51-140)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (32)
  • GitHub Check: Management / Benchmark (amd64, postgres)
  • GitHub Check: Management / Benchmark (amd64, sqlite)
  • GitHub Check: Signal / Unit (amd64)
  • GitHub Check: Relay / Unit (386)
  • GitHub Check: Signal / Unit (386)
  • GitHub Check: Management / Benchmark (API) (amd64, postgres)
  • GitHub Check: Relay / Unit (amd64, -race)
  • GitHub Check: Management / Unit (amd64, sqlite)
  • GitHub Check: Management / Integration (amd64, sqlite)
  • GitHub Check: Management / Benchmark (API) (amd64, sqlite)
  • GitHub Check: Management / Integration (amd64, postgres)
  • GitHub Check: Management / Unit (amd64, postgres)
  • GitHub Check: Management / Unit (amd64, mysql)
  • GitHub Check: Client / Unit (386)
  • GitHub Check: Client / Unit (amd64)
  • GitHub Check: Client (Docker) / Unit
  • GitHub Check: test-docker-compose (mysql)
  • GitHub Check: test-docker-compose (postgres)
  • GitHub Check: test-docker-compose (sqlite)
  • GitHub Check: test-getting-started-script
  • GitHub Check: Client / Unit
  • GitHub Check: Windows
  • GitHub Check: Linux
  • GitHub Check: Darwin
  • GitHub Check: release_ui
  • GitHub Check: release_ui_darwin
  • GitHub Check: release
  • GitHub Check: iOS / Build
  • GitHub Check: Client / Unit
  • GitHub Check: JS / Lint
  • GitHub Check: Android / Build
  • GitHub Check: Client / Unit
🔇 Additional comments (8)
client/firewall/uspfilter/forwarder/icmp.go (8)

5-9: LGTM! Necessary imports for ping fallback.

The new imports support the ping binary fallback mechanism and platform-specific command construction.


20-48: LGTM! Clean separation of echo and non-echo ICMP handling.

The refactored logic properly delegates echo requests to asynchronous handling and forwards non-echo ICMP types when raw socket access is available.


73-99: LGTM! Proper resource management.

The function correctly creates a raw ICMP socket, sends the packet, and handles errors appropriately. The caller is responsible for closing the returned connection as documented.


125-141: LGTM! Proper timeout and buffer sizing.

The function correctly sets a read deadline and sizes the response buffer using the atomic MTU value.


233-245: LGTM! Correct ICMP echo reply synthesis.

The function properly creates an echo reply by copying the data, changing the type, and recalculating the checksum following the standard ICMP checksum algorithm.


247-272: LGTM! Proper IP header construction and injection.

The function correctly constructs an IPv4 header, wraps the ICMP payload, and bypasses the netstack to avoid re-processing by the ICMP handler. The TTL value of 64 is appropriate for local responses.


195-196: The Warn4 logger method exists and is properly implemented.

Verification confirms that Warn4 has been added to the Logger type at client/firewall/uspfilter/log/log.go:171 with the correct signature supporting four arguments. The method call at line 195-196 is valid.


212-231: The original review comment's reasoning is fundamentally incorrect.

The review claims -t is TTL on macOS/BSD, but macOS uses -t <timeout> to specify timeout in seconds and FreeBSD uses -t <timeout> for timeout in seconds. The current code is correct for both platforms.

However, there IS a real issue: OpenBSD uses -w <maxwait>, not -t (which is TTL on OpenBSD), and NetBSD uses -w <deadline> for timeout. The current code incorrectly groups all three BSD variants together on line 225, which fails for OpenBSD and NetBSD.

The correct fix requires splitting BSD platforms:

  • FreeBSD: keep -t
  • OpenBSD: change to -w
  • NetBSD: change to -w

The original review's suggested fix is partially correct by accident but based on false premises.

Likely an incorrect or invalid review comment.

Comment thread client/firewall/uspfilter/forwarder/icmp.go
Comment thread client/firewall/uspfilter/forwarder/icmp.go
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
client/firewall/uspfilter/forwarder/icmp.go (2)

101-123: Send TypeEnd event on error to complete flow tracking.

When forwardICMPPacket fails at line 107, the function returns early without sending a TypeEnd event. This leaves the flow incomplete with only a TypeStart event.

Apply this diff to send an end event on error:

 	conn, err := f.forwardICMPPacket(id, payload, icmpHdr, 5*time.Second)
 	if err != nil {
 		f.logger.Error2("forwarder: Failed to send ICMP packet for %v: %v", epID(id), err)
+		f.sendICMPEvent(nftypes.TypeEnd, flowID, id, uint8(icmpHdr.Type()), uint8(icmpHdr.Code()), uint64(rxBytes), 0)
 		return
 	}

184-210: Send TypeEnd event on error to complete flow tracking.

When the ping binary fails at line 194, the function returns without sending a TypeEnd event, leaving the flow incomplete.

Apply this diff to send an end event on error:

 	pingStart := time.Now()
 	if err := cmd.Run(); err != nil {
 		f.logger.Warn4("forwarder: Ping binary failed for %v type %v code %v: %v", epID(id),
 			icmpHdr.Type(), icmpHdr.Code(), err)
+		f.sendICMPEvent(nftypes.TypeEnd, flowID, id, uint8(icmpHdr.Type()), uint8(icmpHdr.Code()), uint64(rxBytes), 0)
 		return
 	}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 099870d and ca21a98.

📒 Files selected for processing (2)
  • client/firewall/uspfilter/forwarder/icmp.go (4 hunks)
  • client/firewall/uspfilter/forwarder/udp.go (8 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4777
File: client/firewall/iptables/acl_linux.go:439-450
Timestamp: 2025-11-13T15:19:32.799Z
Learning: In the netbird client firewall iptables implementation (client/firewall/iptables/), IPv6 is not currently handled or supported.
🧬 Code graph analysis (2)
client/firewall/uspfilter/forwarder/udp.go (1)
client/firewall/uspfilter/forwarder/forwarder.go (1)
  • Forwarder (35-49)
client/firewall/uspfilter/forwarder/icmp.go (1)
client/firewall/uspfilter/forwarder/forwarder.go (2)
  • Forwarder (35-49)
  • New (51-140)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (30)
  • GitHub Check: Client / Unit (amd64)
  • GitHub Check: Relay / Unit (386)
  • GitHub Check: Management / Benchmark (API) (amd64, postgres)
  • GitHub Check: Management / Unit (amd64, mysql)
  • GitHub Check: Management / Benchmark (API) (amd64, sqlite)
  • GitHub Check: Relay / Unit (amd64, -race)
  • GitHub Check: Management / Integration (amd64, postgres)
  • GitHub Check: Management / Integration (amd64, sqlite)
  • GitHub Check: Management / Unit (amd64, sqlite)
  • GitHub Check: Signal / Unit (amd64)
  • GitHub Check: Management / Benchmark (amd64, sqlite)
  • GitHub Check: Management / Unit (amd64, postgres)
  • GitHub Check: Management / Benchmark (amd64, postgres)
  • GitHub Check: Signal / Unit (386)
  • GitHub Check: Client / Unit (386)
  • GitHub Check: Client (Docker) / Unit
  • GitHub Check: release_ui_darwin
  • GitHub Check: release_ui
  • GitHub Check: release
  • GitHub Check: Client / Unit
  • GitHub Check: Android / Build
  • GitHub Check: test-docker-compose (sqlite)
  • GitHub Check: test-docker-compose (mysql)
  • GitHub Check: test-getting-started-script
  • GitHub Check: test-docker-compose (postgres)
  • GitHub Check: JS / Lint
  • GitHub Check: Client / Unit
  • GitHub Check: Darwin
  • GitHub Check: Linux
  • GitHub Check: Windows
🔇 Additional comments (4)
client/firewall/uspfilter/forwarder/udp.go (2)

352-354: Good addition of io.EOF to closed-error detection.

Treating io.EOF as a terminal condition in isClosedError is appropriate, as EOF signals a closed connection and should not be logged as an unexpected error.


180-180: Signature change verified and correct.

The web search confirms that gonet.NewUDPConn in the upgraded gvisor/netstack has signature func NewUDPConn(wq *waiter.Queue, ep tcpip.Endpoint) *UDPConn. The code at line 180 (gonet.NewUDPConn(&wq, ep)) correctly matches this signature, with the stack parameter properly removed as part of the netstack upgrade.

client/firewall/uspfilter/forwarder/icmp.go (2)

247-272: Good implementation of ICMP reply injection.

The injectICMPReply method correctly:

  • Constructs a proper IPv4 header with appropriate fields
  • Calculates and sets the IP checksum
  • Bypasses netstack to avoid looping through the ICMP handler
  • Returns the injected size for flow tracking

212-231: I need to verify the flags across all platforms mentioned. The web search already revealed important information about macOS that contradicts the review comment. Let me search for the other platforms:

Based on my verification, the review comment contains fundamental inaccuracies regarding the macOS ping flags.

The review comment is incorrect and should be disregarded.

Evidence from official documentation:

  • Linux/Android: -W specifies time to wait for a response in seconds, with -w setting the timeout for the entire program session. The code correctly uses -W for timeout.

  • FreeBSD/OpenBSD/NetBSD: -t specifies a timeout in seconds before ping exits. The code correctly uses -t for timeout on these platforms.

  • Windows: -w sets timeout in milliseconds. The code correctly multiplies timeoutSec by 1000 to convert to milliseconds.

  • macOS/iOS: The review's claim is incorrect. From the earlier web search, -t timeout on macOS is "overall timeout in seconds before ping exits regardless of packets received." The code correctly uses -t with timeout in seconds. The review mistakenly claims -t is TTL and suggests using -W, but on macOS, -W uses milliseconds, not seconds, which would be inconsistent with the code's handling of seconds.

The platform-specific ping flags in the code are correct and consistent with official documentation across all platforms.

Likely an incorrect or invalid review comment.

Comment thread client/firewall/uspfilter/forwarder/icmp.go
Comment thread client/firewall/uspfilter/forwarder/icmp.go
@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @client/firewall/uspfilter/forwarder/icmp.go:
- Around line 212-231: In buildPingCommand fix the incorrect use of "-t" (TTL)
on darwin/ios and BSDs: replace the "-t" flag with "-W" and pass the timeout in
milliseconds (e.g. timeoutSec * 1000) for the "darwin","ios" and the
"freebsd","openbsd","netbsd" switch cases; also ensure the darwin case keeps the
"-q" flag and add "-q" to the BSD case if supported so behavior matches other
platforms while still relying on the context timeout as a fallback.
🧹 Nitpick comments (4)
client/iface/bind/ice_bind.go (1)

34-44: Non-IPv4 receiver path lacks batch optimization.

The non-IPv4 fallback path only reads a single packet per call (bufs[0]) and doesn't leverage batch reading capabilities that the IPv4 path uses. While this is functionally correct, it may impact performance for non-IPv4 or fallback scenarios.

This is likely an intentional simplification for a less common code path, but consider documenting this limitation if performance becomes a concern.

client/firewall/uspfilter/forwarder/icmp.go (3)

50-71: Consider TypeEnd event for rate-limited requests.

When the rate limit is exceeded (lines 66-69), a TypeStart event was already sent (line 24 in handleICMP), but no corresponding TypeEnd event is sent. While the learned pattern indicates TypeEnd is primarily for completed echo flows, having a TypeStart without TypeEnd for rate-limited requests may cause incomplete flow tracking.

Consider sending a TypeEnd event in the rate-limit case to maintain flow consistency:

Optional: Send TypeEnd for rate-limited requests
 	default:
 		f.logger.Debug3("forwarder: ICMP rate limit exceeded for %v type %v code %v",
 			epID(id), icmpHdr.Type(), icmpHdr.Code())
+		f.sendICMPEvent(nftypes.TypeEnd, flowID, id, uint8(icmpHdr.Type()), uint8(icmpHdr.Code()), 0, 0)
 	}

101-123: Consider sending TypeEnd event on socket forward failure.

When forwardICMPPacket fails (lines 107-108), a TypeStart event was already emitted (line 24 in handleICMP), but no TypeEnd event is sent. While the learned pattern focuses TypeEnd on complete bidirectional flows, leaving a TypeStart without a matching TypeEnd may impact flow tracking consistency.

For robust flow lifecycle tracking, consider sending TypeEnd with zero metrics on failure:

Send TypeEnd on error
 	conn, err := f.forwardICMPPacket(id, payload, icmpHdr, 5*time.Second)
 	if err != nil {
 		f.logger.Error2("forwarder: Failed to send ICMP packet for %v: %v", epID(id), err)
+		f.sendICMPEvent(nftypes.TypeEnd, flowID, id, uint8(icmpHdr.Type()), uint8(icmpHdr.Code()), uint64(rxBytes), 0)
 		return
 	}

184-210: Consider sending TypeEnd event on ping failure.

When the ping command fails (lines 194-197), a TypeStart event was already emitted but no TypeEnd event is sent. For consistent flow lifecycle tracking, consider sending TypeEnd with zero txBytes on failure:

Send TypeEnd on ping error
 	if err := cmd.Run(); err != nil {
 		f.logger.Warn4("forwarder: Ping binary failed for %v type %v code %v: %v", epID(id),
 			icmpHdr.Type(), icmpHdr.Code(), err)
+		f.sendICMPEvent(nftypes.TypeEnd, flowID, id, uint8(icmpHdr.Type()), uint8(icmpHdr.Code()), uint64(rxBytes), 0)
 		return
 	}
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3b40bc9 and 1b1310d.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (7)
  • client/firewall/uspfilter/forwarder/endpoint.go
  • client/firewall/uspfilter/forwarder/forwarder.go
  • client/firewall/uspfilter/forwarder/icmp.go
  • client/firewall/uspfilter/forwarder/udp.go
  • client/firewall/uspfilter/log/log.go
  • client/iface/bind/ice_bind.go
  • go.mod
🚧 Files skipped from review as they are similar to previous changes (3)
  • client/firewall/uspfilter/log/log.go
  • client/firewall/uspfilter/forwarder/forwarder.go
  • client/firewall/uspfilter/forwarder/endpoint.go
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4792
File: client/firewall/uspfilter/forwarder/icmp.go:32-48
Timestamp: 2025-11-15T14:46:06.743Z
Learning: In the netbird userspace firewall forwarder (client/firewall/uspfilter/forwarder/), the boolean return value from ICMP/UDP handlers indicates packet ownership to netstack: `true` means "I handled this packet, don't process it further" and `false` means "I didn't handle it, netstack should handle it". This is used to prevent netstack from generating its own replies even when forwarding fails.
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4792
File: client/firewall/uspfilter/forwarder/icmp.go:32-48
Timestamp: 2025-11-16T19:27:08.018Z
Learning: In the netbird userspace firewall forwarder (client/firewall/uspfilter/forwarder/), flow events (TypeStart/TypeEnd) are only sent for ICMP echo requests/replies to track the complete bidirectional flow. Other ICMP types (Time Exceeded, Destination Unreachable, etc.) only get a TypeStart event without a corresponding TypeEnd event, as they are typically one-way notifications that don't require complete lifecycle tracking.
📚 Learning: 2025-11-15T14:46:06.743Z
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4792
File: client/firewall/uspfilter/forwarder/icmp.go:32-48
Timestamp: 2025-11-15T14:46:06.743Z
Learning: In the netbird userspace firewall forwarder (client/firewall/uspfilter/forwarder/), the boolean return value from ICMP/UDP handlers indicates packet ownership to netstack: `true` means "I handled this packet, don't process it further" and `false` means "I didn't handle it, netstack should handle it". This is used to prevent netstack from generating its own replies even when forwarding fails.

Applied to files:

  • client/firewall/uspfilter/forwarder/udp.go
  • client/firewall/uspfilter/forwarder/icmp.go
📚 Learning: 2025-11-16T19:27:08.018Z
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4792
File: client/firewall/uspfilter/forwarder/icmp.go:32-48
Timestamp: 2025-11-16T19:27:08.018Z
Learning: In the netbird userspace firewall forwarder (client/firewall/uspfilter/forwarder/), flow events (TypeStart/TypeEnd) are only sent for ICMP echo requests/replies to track the complete bidirectional flow. Other ICMP types (Time Exceeded, Destination Unreachable, etc.) only get a TypeStart event without a corresponding TypeEnd event, as they are typically one-way notifications that don't require complete lifecycle tracking.

Applied to files:

  • client/firewall/uspfilter/forwarder/icmp.go
🧬 Code graph analysis (2)
client/firewall/uspfilter/forwarder/udp.go (1)
client/firewall/uspfilter/forwarder/forwarder.go (1)
  • Forwarder (35-49)
client/iface/bind/ice_bind.go (3)
client/net/listener_listen.go (2)
  • UDPConn (58-62)
  • PacketConn (37-41)
client/iface/udpmux/universal.go (1)
  • UDPConn (119-127)
client/iface/bind/endpoint.go (1)
  • Endpoint (9-9)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: Linux
  • GitHub Check: Darwin
  • GitHub Check: Windows
  • GitHub Check: Android / Build
  • GitHub Check: iOS / Build
  • GitHub Check: Build Cache
  • GitHub Check: Client / Unit
  • GitHub Check: JS / Lint
  • GitHub Check: FreeBSD Port / Build & Test
  • GitHub Check: release_ui
  • GitHub Check: release
  • GitHub Check: release_ui_darwin
  • GitHub Check: Client / Unit
  • GitHub Check: Client / Unit
🔇 Additional comments (11)
client/firewall/uspfilter/forwarder/udp.go (3)

352-354: LGTM!

Treating io.EOF as a closed error condition is appropriate and aligns with the semantic meaning of EOF (end-of-stream). This prevents unnecessary error logging when connections naturally close.


135-213: LGTM!

The boolean return value semantics are consistently applied throughout handleUDP:

  • Returns false when the packet cannot be handled (context done, dial errors, endpoint errors)
  • Returns true when the packet is owned/handled (existing connection, successful setup)

This aligns with the learned pattern where the return value indicates packet ownership to netstack.

Based on learnings, the boolean return value prevents netstack from generating its own replies.


180-180: The gonet.NewUDPConn signature has been correctly updated for the gvisor bump.

The code at line 180 uses the new 2-parameter signature gonet.NewUDPConn(&wq, ep), which is correct for the current gvisor version (v0.0.0-20251031020517-ecfcdd2f171c). The stack parameter has been properly removed as required by the updated gvisor API.

client/firewall/uspfilter/forwarder/icmp.go (4)

20-48: LGTM!

The refactored ICMP handling properly separates echo and non-echo paths:

  • Echo requests are handled asynchronously via handleICMPEcho
  • Non-echo types are forwarded directly when raw access is available
  • Returning true on line 41 even when forwarding fails is correct per the learned pattern—it signals packet ownership to netstack, preventing it from generating its own replies

Based on learnings, only echo requests/replies track complete flows with TypeEnd events, while other ICMP types only emit TypeStart.


73-99: LGTM!

The forwardICMPPacket function is well-designed:

  • Properly uses context with timeout for socket creation
  • Handles write errors with cleanup before returning
  • Clearly documents caller responsibility for closing the connection
  • Provides good trace logging for observability

125-141: LGTM!

The handleEchoResponse function properly:

  • Uses atomic MTU access for buffer sizing
  • Sets appropriate read deadlines
  • Distinguishes timeout errors from other failures
  • Returns meaningful size information for metrics

233-272: LGTM!

The helper functions for synthesizing and injecting ICMP replies are well-implemented:

  • synthesizeEchoReply properly copies data, updates type, and recalculates checksums
  • injectICMPReply constructs valid IPv4 headers with correct field swapping and checksum calculation
  • Properly bypasses netstack via endpoint.device.CreateOutboundPacket to avoid infinite loops (line 266)
go.mod (3)

25-25: Verify security advisories for significant dependency version bumps.

The dependency versions cited are present in go.mod (google.golang.org/api v0.249.0, OpenTelemetry instrumentation v0.61.0, and others). To complete verification, run go list -u -m all and govulncheck ./... locally to check for security advisories and breaking changes in these updates.


122-122: The gvisor version v0.0.0-20251031020517-ecfcdd2f171c exists and is compatible with the wireguard-go fork.

The gvisor bump is verified: the version exists and is properly configured in go.mod with the corresponding wireguard-go fork replacement (github.com/netbirdio/wireguard-go v0.0.0-20251115110821-938e8b40e2f3).


266-266: Verify the netbirdio/wireguard-go dependency before merging.

The go.mod update references a dependency on netbirdio/wireguard-go (v0.0.0-20251115110821-938e8b40e2f3), but the associated PR status could not be verified through standard GitHub channels. Since netbirdio/wireguard-go appears to be a mirror repository, manually confirm the dependency is stable and the referenced work is complete before merging this PR.

client/iface/bind/ice_bind.go (1)

30-33: CreateReceiverFn signature correctly generalizes receiver creation for multiple packet connection types.

The method signature change from CreateIPv4ReceiverFn to CreateReceiverFn with wgConn.BatchReader parameter properly aligns with wireguard-go's interface contract. The implementation correctly handles IPv4 connections via type assertion while providing a fallback for non-IPv4 paths using standard net.UDPConn semantics.

Comment thread client/firewall/uspfilter/forwarder/icmp.go
Comment thread client/iface/bind/ice_bind.go
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @client/firewall/uspfilter/forwarder/icmp.go:
- Line 21: The goroutine is capturing icmpHdr which points into the original
packet buffer (created via
header.ICMPv4(pkt.TransportHeader().View().AsSlice())), causing a data race when
the packet is recycled; fix by constructing the ICMP header from the copied
icmpData before spawning the goroutine (e.g., create a new
header.ICMPv4(icmpData) and use that in the goroutine instead of the original
icmpHdr), ensuring the goroutine only references the safe, copied slice.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1b1310d and bb0ea93.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (3)
  • client/firewall/uspfilter/forwarder/icmp.go
  • client/iface/bind/ice_bind.go
  • go.mod
🚧 Files skipped from review as they are similar to previous changes (1)
  • go.mod
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4792
File: client/firewall/uspfilter/forwarder/icmp.go:32-48
Timestamp: 2025-11-15T14:46:06.743Z
Learning: In the netbird userspace firewall forwarder (client/firewall/uspfilter/forwarder/), the boolean return value from ICMP/UDP handlers indicates packet ownership to netstack: `true` means "I handled this packet, don't process it further" and `false` means "I didn't handle it, netstack should handle it". This is used to prevent netstack from generating its own replies even when forwarding fails.
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4792
File: client/firewall/uspfilter/forwarder/icmp.go:32-48
Timestamp: 2025-11-16T19:27:08.018Z
Learning: In the netbird userspace firewall forwarder (client/firewall/uspfilter/forwarder/), flow events (TypeStart/TypeEnd) are only sent for ICMP echo requests/replies to track the complete bidirectional flow. Other ICMP types (Time Exceeded, Destination Unreachable, etc.) only get a TypeStart event without a corresponding TypeEnd event, as they are typically one-way notifications that don't require complete lifecycle tracking.
📚 Learning: 2025-11-15T14:46:06.743Z
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4792
File: client/firewall/uspfilter/forwarder/icmp.go:32-48
Timestamp: 2025-11-15T14:46:06.743Z
Learning: In the netbird userspace firewall forwarder (client/firewall/uspfilter/forwarder/), the boolean return value from ICMP/UDP handlers indicates packet ownership to netstack: `true` means "I handled this packet, don't process it further" and `false` means "I didn't handle it, netstack should handle it". This is used to prevent netstack from generating its own replies even when forwarding fails.

Applied to files:

  • client/firewall/uspfilter/forwarder/icmp.go
📚 Learning: 2025-11-16T19:27:08.018Z
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4792
File: client/firewall/uspfilter/forwarder/icmp.go:32-48
Timestamp: 2025-11-16T19:27:08.018Z
Learning: In the netbird userspace firewall forwarder (client/firewall/uspfilter/forwarder/), flow events (TypeStart/TypeEnd) are only sent for ICMP echo requests/replies to track the complete bidirectional flow. Other ICMP types (Time Exceeded, Destination Unreachable, etc.) only get a TypeStart event without a corresponding TypeEnd event, as they are typically one-way notifications that don't require complete lifecycle tracking.

Applied to files:

  • client/firewall/uspfilter/forwarder/icmp.go
📚 Learning: 2026-01-07T10:08:00.555Z
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4792
File: client/firewall/uspfilter/forwarder/icmp.go:212-231
Timestamp: 2026-01-07T10:08:00.555Z
Learning: OS-specific ping flag handling: macOS/iOS and FreeBSD use -t timeout; OpenBSD/NetBSD use -w timeout. In code that shells out to ping (e.g., icmp.go and related files), implement OS-aware flag selection. Use build tags or GOOS checks to choose the correct flag, and encapsulate this in a helper (e.g., getPingTimeoutFlag()) to avoid hard-coding across platforms. Document the OS assumption and ensure tests cover the differing flags.

Applied to files:

  • client/firewall/uspfilter/forwarder/icmp.go
🧬 Code graph analysis (1)
client/firewall/uspfilter/forwarder/icmp.go (1)
client/firewall/uspfilter/forwarder/forwarder.go (2)
  • Forwarder (35-49)
  • New (51-140)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: release
  • GitHub Check: release_ui
  • GitHub Check: FreeBSD Port / Build & Test
  • GitHub Check: Client / Unit
  • GitHub Check: Client / Unit
  • GitHub Check: Build Cache
  • GitHub Check: iOS / Build
  • GitHub Check: Linux
  • GitHub Check: Windows
  • GitHub Check: Android / Build
  • GitHub Check: JS / Lint
  • GitHub Check: Check External GPL/AGPL Licenses
🔇 Additional comments (8)
client/iface/bind/ice_bind.go (2)

29-31: LGTM: Interface generalization improves flexibility.

The change from concrete *ipv4.PacketConn to wgConn.BatchReader interface aligns with the wireguard-go update and improves flexibility. The method name change from CreateIPv4ReceiverFn to CreateReceiverFn is also more accurate.


162-233: BatchReader interface is properly available from the configured wireguard-go fork.

The BatchReader interface is imported from golang.zx2c4.com/wireguard/conn (via the netbirdio/wireguard-go fork v0.0.0-20260107100953-33b7c9d03db0 already configured in go.mod), and the ReadBatch method is called correctly at lines 187 and 196. The implementation is consistent across both function signatures and integrates properly with the updated dependency.

client/firewall/uspfilter/forwarder/icmp.go (6)

73-99: LGTM: Clean error handling and resource management.

The function properly creates the ICMP socket, writes the packet, and returns the connection with clear ownership semantics. Error paths correctly close the connection when needed and wrap errors with context.


125-141: LGTM: Proper timeout handling and atomic MTU access.

The function correctly sets a read deadline, handles timeout errors gracefully, and uses atomic load for the MTU value. The return value properly indicates the injected packet size.


212-233: LGTM: Correct platform-specific timeout flags.

The function correctly uses platform-specific ping timeout flags: -t for macOS/iOS/FreeBSD, -w for OpenBSD/NetBSD/Windows, and -W for Linux/Android, consistent with their respective man pages.

Based on learnings, OS-specific ping flag handling is implemented correctly.


235-247: LGTM: Proper ICMP echo reply synthesis.

The function correctly creates an echo reply by copying the request data, changing the type to EchoReply, and recalculating the checksum. The implementation follows standard ICMP reply construction.


249-274: LGTM: Correct IP packet construction and injection.

The function properly constructs an IPv4 packet with the ICMP payload, calculates checksums, and bypasses netstack to inject directly via the endpoint device. This correctly prevents the packet from looping back through the ICMP handler.


32-47: LGTM: Correct non-echo ICMP handling.

The non-echo ICMP path correctly returns false when raw socket access is unavailable (letting netstack handle it), and returns true after forwarding when raw access is available. Per the design, TypeEnd events are intentionally only sent for echo requests/replies, so omitting TypeEnd here is correct.

Based on learnings, the return value semantics and flow tracking behavior are correct.

Comment thread client/firewall/uspfilter/forwarder/icmp.go
pappz
pappz previously approved these changes Jan 7, 2026
pappz
pappz previously approved these changes Jan 7, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @client/iface/bind/ice_bind.go:
- Around line 34-44: The fallback packet receiver returned in ice_bind.go
currently reads a single packet via conn.ReadFromUDPAddrPort but does not filter
STUN messages, record transport activity, or interact with the UDP mux like the
IPv4 path; modify that returned func to call filterOutStunMessages on the
received buf (and skip returning the packet if it’s a STUN message), update
activity tracking by invoking the same recordTransportActivity logic used in the
IPv4 branch (using the StdNetEndpoint/wgConn.StdNetEndpoint), and ensure any use
of s.udpMux/GetICEMux() mirrors the IPv4 path’s handling (propagate or handle
the error as callers expect) so STUNs are consistently filtered and activity is
recorded even in the fallback path.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f13edb2 and a8b3dc1.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (2)
  • client/iface/bind/ice_bind.go
  • go.mod
🚧 Files skipped from review as they are similar to previous changes (1)
  • go.mod
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4792
File: client/firewall/uspfilter/forwarder/icmp.go:32-48
Timestamp: 2025-11-15T14:46:06.743Z
Learning: In the netbird userspace firewall forwarder (client/firewall/uspfilter/forwarder/), the boolean return value from ICMP/UDP handlers indicates packet ownership to netstack: `true` means "I handled this packet, don't process it further" and `false` means "I didn't handle it, netstack should handle it". This is used to prevent netstack from generating its own replies even when forwarding fails.
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4792
File: client/firewall/uspfilter/forwarder/icmp.go:32-48
Timestamp: 2025-11-16T19:27:08.018Z
Learning: In the netbird userspace firewall forwarder (client/firewall/uspfilter/forwarder/), flow events (TypeStart/TypeEnd) are only sent for ICMP echo requests/replies to track the complete bidirectional flow. Other ICMP types (Time Exceeded, Destination Unreachable, etc.) only get a TypeStart event without a corresponding TypeEnd event, as they are typically one-way notifications that don't require complete lifecycle tracking.
Learnt from: lixmal
Repo: netbirdio/netbird PR: 4777
File: client/firewall/iptables/acl_linux.go:439-450
Timestamp: 2025-11-13T15:19:32.799Z
Learning: In the netbird client firewall iptables implementation (client/firewall/iptables/), IPv6 is not currently handled or supported.
🧬 Code graph analysis (1)
client/iface/bind/ice_bind.go (3)
client/net/listener_listen.go (2)
  • UDPConn (58-62)
  • PacketConn (37-41)
client/iface/udpmux/universal.go (1)
  • UDPConn (119-127)
client/iface/bind/endpoint.go (1)
  • Endpoint (9-9)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (15)
  • GitHub Check: Darwin
  • GitHub Check: Linux
  • GitHub Check: Windows
  • GitHub Check: Client / Unit
  • GitHub Check: Build Cache
  • GitHub Check: Android / Build
  • GitHub Check: JS / Lint
  • GitHub Check: iOS / Build
  • GitHub Check: FreeBSD Port / Build & Test
  • GitHub Check: Client / Unit
  • GitHub Check: release_ui_darwin
  • GitHub Check: release_ui
  • GitHub Check: release
  • GitHub Check: Client / Unit
  • GitHub Check: Check External GPL/AGPL Licenses
🔇 Additional comments (1)
client/iface/bind/ice_bind.go (1)

30-33: LGTM: Clean generalization with safe fallback.

The function signature change from CreateIPv4ReceiverFn to CreateReceiverFn accepting wgConn.BatchReader properly accommodates the updated wireguard-go API while preserving the existing IPv4-specific path through safe type assertion.

Comment thread client/iface/bind/ice_bind.go
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Jan 8, 2026

@lixmal lixmal merged commit e8863fb into main Jan 8, 2026
40 checks passed
@lixmal lixmal deleted the forwarder-ping branch January 8, 2026 18:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants