Repository: quic-go/quic-go
Pull request #5094 (2025-04-29 09:13:26)

fix: parse ifindex from packet correctly
Updates #5088 

Now `ipi_ifindex` can be properly parsed from the packet.

I guess this probably won't affect `darwin`, since it seems they only build `small-endian` devices today, but it's decided at compile time anyway and doesn't introduce additional overhead.

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/quic-go/quic-go/pull/5094?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 84.18%. Comparing base [(`5daf5b6`)](https://app.codecov.io/gh/quic-go/quic-go/commit/5daf5b6535c4bb12fc918808aeb8686e13c89104?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go) to head [(`1eda9b1`)](https://app.codecov.io/gh/quic-go/quic-go/commit/1eda9b1f002f8b4d20a486f69425d16dc4d92abc?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go).

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #5094      +/-   ##
==========================================
+ Coverage   84.12%   84.18%   +0.06%     
==========================================
  Files         153      150       -3     
  Lines       16994    16944      -50     
==========================================
- Hits        14295    14263      -32     
+ Misses       2165     2150      -15     
+ Partials      534      531       -3     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/quic-go/quic-go/pull/5094?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>
Zxilly: Yes, s390x runs on big-endian
Zxilly: I don't think this fixes the ecn issue on the s390x, it's a basic fix and we need more work.
marten-seemann: > I don't think this fixes the ecn issue on the s390x, it's a basic fix and we need more work.

I edited your original issue, so now it's about the interface index.

Would you be interested in contributing a fix for ECN as well? Do you have any suggestion how we could test this in CI (not required, but in my experience, things that are not getting tested in CI tend to break sooner or later)?

Patch:
diff --git a/http3/server.go b/http3/server.go
index 3353f0af..6773a96c 100644
--- a/http3/server.go
+++ b/http3/server.go
@@ -264,6 +264,11 @@ func (s *Server) decreaseConnCount() {
 // ServeQUICConn serves a single QUIC connection.
 func (s *Server) ServeQUICConn(conn quic.Connection) error {
 	s.mutex.Lock()
+	if s.closed {
+		s.mutex.Unlock()
+		return http.ErrServerClosed
+	}
+
 	s.init()
 	s.mutex.Unlock()
 
diff --git a/sys_conn_helper_darwin.go b/sys_conn_helper_darwin.go
index 545502dd..a04bfb3c 100644
--- a/sys_conn_helper_darwin.go
+++ b/sys_conn_helper_darwin.go
@@ -30,7 +30,7 @@ func parseIPv4PktInfo(body []byte) (ip netip.Addr, ifIndex uint32, ok bool) {
 	if len(body) != 12 {
 		return netip.Addr{}, 0, false
 	}
-	return netip.AddrFrom4(*(*[4]byte)(body[8:12])), binary.LittleEndian.Uint32(body), true
+	return netip.AddrFrom4(*(*[4]byte)(body[8:12])), binary.NativeEndian.Uint32(body), true
 }
 
 func isGSOEnabled(syscall.RawConn) bool { return false }
diff --git a/sys_conn_helper_linux.go b/sys_conn_helper_linux.go
index eec12719..9a890cbe 100644
--- a/sys_conn_helper_linux.go
+++ b/sys_conn_helper_linux.go
@@ -58,7 +58,7 @@ func parseIPv4PktInfo(body []byte) (ip netip.Addr, ifIndex uint32, ok bool) {
 	if len(body) != 12 {
 		return netip.Addr{}, 0, false
 	}
-	return netip.AddrFrom4(*(*[4]byte)(body[8:12])), binary.LittleEndian.Uint32(body), true
+	return netip.AddrFrom4(*(*[4]byte)(body[8:12])), binary.NativeEndian.Uint32(body), true
 }
 
 // isGSOEnabled tests if the kernel supports GSO.
diff --git a/sys_conn_oob.go b/sys_conn_oob.go
index 5ed1b656..974ff049 100644
--- a/sys_conn_oob.go
+++ b/sys_conn_oob.go
@@ -222,7 +222,7 @@ func (c *oobConn) ReadPacket() (receivedPacket, error) {
 				// };
 				if len(body) == 20 {
 					p.info.addr = netip.AddrFrom16(*(*[16]byte)(body[:16])).Unmap()
-					p.info.ifIndex = binary.LittleEndian.Uint32(body[16:])
+					p.info.ifIndex = binary.NativeEndian.Uint32(body[16:])
 				} else {
 					invalidCmsgOnceV6.Do(func() {
 						log.Printf("Received invalid IPv6 packet info control message: %+x. "+


Test patch:
diff --git a/http3/server_test.go b/http3/server_test.go
index 3f6f29a3..43dfc168 100644
--- a/http3/server_test.go
+++ b/http3/server_test.go
@@ -883,6 +883,7 @@ var _ = Describe("Server", func() {
 		serv := &Server{}
 		Expect(serv.Close()).To(Succeed())
 		Expect(serv.ListenAndServeTLS(testdata.GetCertificatePaths())).To(MatchError(http.ErrServerClosed))
+		Expect(serv.ServeQUICConn(nil)).To(MatchError(http.ErrServerClosed))
 	})
 
 	It("handles concurrent Serve and Close", func() {