1717package procnet
1818
1919import (
20+ "encoding/binary"
2021 "encoding/hex"
2122 "fmt"
2223 "net"
@@ -72,12 +73,20 @@ func removeEmpty(array []string) (results []string) {
7273//
7374// See https://serverfault.com/questions/592574/why-does-proc-net-tcp6-represents-1-as-1000
7475//
75- // ParseAddress is expected to be used for /proc/net/{tcp,tcp6} entries on
76- // little endian machines.
77- // Not sure how those entries look like on big endian machines.
78- // All the code below is copied from the lima project in https://github.com/lima-vm/lima/blob/v0.8.3/pkg/guestagent/procnettcp/procnettcp.go#L95-L137
76+ // ParseAddress parses the entry using the current host's native byte order.
77+ // Use ParseAddressWithByteOrder to parse an entry whose byte order is known.
78+ // The parsing logic is derived from the lima project in https://github.com/lima-vm/lima/blob/v0.8.3/pkg/guestagent/procnettcp/procnettcp.go#L95-L137
7979// and is licensed under the Apache License, Version 2.0
8080func ParseAddress (s string ) (net.IP , uint16 , error ) {
81+ return ParseAddressWithByteOrder (s , binary .NativeEndian )
82+ }
83+
84+ // ParseAddressWithByteOrder is like ParseAddress but takes the byte order of
85+ // the /proc data explicitly. The kernel writes each 4-byte group of the address
86+ // in the host's native byte order (little-endian on x86/arm64, big-endian on
87+ // s390x), so each group is read with that order and rewritten in network order
88+ // to build the net.IP.
89+ func ParseAddressWithByteOrder (s string , order binary.ByteOrder ) (net.IP , uint16 , error ) {
8190 split := strings .SplitN (s , ":" , 2 )
8291 if len (split ) != 2 {
8392 return nil , 0 , fmt .Errorf ("unparsable address %q" , s )
@@ -92,13 +101,11 @@ func ParseAddress(s string) (net.IP, uint16, error) {
92101 ipBytes := make ([]byte , len (split [0 ])/ 2 ) // 4 bytes (8 chars) or 16 bytes (32 chars)
93102 for i := 0 ; i < len (split [0 ])/ 8 ; i ++ {
94103 quartet := split [0 ][8 * i : 8 * (i + 1 )]
95- quartetLE , err := hex .DecodeString (quartet ) // surprisingly little endian, per 4 bytes
104+ quartetBytes , err := hex .DecodeString (quartet )
96105 if err != nil {
97106 return nil , 0 , fmt .Errorf ("unparsable address %q: unparsable quartet %q: %w" , s , quartet , err )
98107 }
99- for j := 0 ; j < len (quartetLE ); j ++ {
100- ipBytes [4 * i + len (quartetLE )- 1 - j ] = quartetLE [j ]
101- }
108+ binary .BigEndian .PutUint32 (ipBytes [4 * i :], order .Uint32 (quartetBytes ))
102109 }
103110 ip := net .IP (ipBytes )
104111
0 commit comments