3
3
package agentssh
4
4
5
5
import (
6
+ "errors"
6
7
"fmt"
7
8
"os"
8
9
@@ -11,24 +12,37 @@ import (
11
12
)
12
13
13
14
func getListeningPortProcessCmdline (port uint32 ) (string ,error ) {
14
- tabs , err := netstat . TCPSocks ( func (s * netstat.SockTabEntry )bool {
15
+ acceptFn := func (s * netstat.SockTabEntry )bool {
15
16
return s .LocalAddr != nil && uint32 (s .LocalAddr .Port )== port
16
- })
17
- if err != nil {
18
- return "" ,xerrors .Errorf ("inspect port %d: %w" ,port ,err )
19
17
}
20
- if len (tabs )== 0 {
21
- return "" ,nil
18
+ tabs4 ,err4 := netstat .TCPSocks (acceptFn )
19
+ tabs6 ,err6 := netstat .TCP6Socks (acceptFn )
20
+
21
+ // In the common case, we want to check ipv4 listening addresses. If this
22
+ // fails, we should return an error. We also need to check ipv6. The
23
+ // assumption is, if we have an err4, and 0 ipv6 addresses listed, then we are
24
+ // interested in the err4 (and vice versa). So return both errors (at least 1
25
+ // is non-nil) if the other list is empty.
26
+ if (err4 != nil && len (tabs6 )== 0 )|| (err6 != nil && len (tabs4 )== 0 ) {
27
+ return "" ,xerrors .Errorf ("inspect port %d: %w" ,port ,errors .Join (err4 ,err6 ))
22
28
}
23
29
24
- // Defensive check.
25
- if tabs [0 ].Process == nil {
30
+ var proc * netstat.Process
31
+ if len (tabs4 )> 0 {
32
+ proc = tabs4 [0 ].Process
33
+ }else if len (tabs6 )> 0 {
34
+ proc = tabs6 [0 ].Process
35
+ }
36
+ if proc == nil {
37
+ // Either nothing is listening on this port or we were unable to read the
38
+ // process details (permission issues reading /proc/$pid/* potentially).
39
+ // Or, perhaps /proc/net/tcp{,6} is not listing the port for some reason.
26
40
return "" ,nil
27
41
}
28
42
29
43
// The process name provided by go-netstat does not include the full command
30
44
// line so grab that instead.
31
- pid := tabs [ 0 ]. Process .Pid
45
+ pid := proc .Pid
32
46
data ,err := os .ReadFile (fmt .Sprintf ("/proc/%d/cmdline" ,pid ))
33
47
if err != nil {
34
48
return "" ,xerrors .Errorf ("read /proc/%d/cmdline: %w" ,pid ,err )