-
Notifications
You must be signed in to change notification settings - Fork 6
/
netstat_tulpen.go
98 lines (84 loc) · 2.33 KB
/
netstat_tulpen.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/*
Sample program to the netstat package. Prints almost the same output as `netstat -tulpen`.
Differences I've seen:
- Some hints are missing e.g. Not all processes could be identified,...
- udp shows State CLOSE instead of nothing
*/
package main
import (
"fmt"
"path/filepath"
"strconv"
"strings"
"github.com/bastjan/netstat"
)
var header = []string{"Proto", "Recv-Q", "Send-Q", "Local Address", "Foreign Address", "State", "User", "Inode", "PID/Program name"}
func main() {
out := [][]string{header}
out = append(out, formatConnections(netstat.TCP)...)
out = append(out, formatConnections(netstat.TCP6)...)
out = append(out, formatConnections(netstat.UDP)...)
out = append(out, formatConnections(netstat.UDP6)...)
printAligned(out)
}
func formatConnections(loc *netstat.Protocol) [][]string {
connections, _ := loc.Connections()
results := make([][]string, 0, len(connections))
for _, conn := range connections {
if !isListening(conn) {
continue
}
results = append(results, []string{
conn.Protocol.Name,
strconv.FormatUint(conn.ReceiveQueue, 10),
strconv.FormatUint(conn.TransmitQueue, 10),
fmt.Sprintf("%s:%s", conn.IP, formatPort(conn.Port)),
fmt.Sprintf("%s:%s", conn.RemoteIP, formatPort(conn.RemotePort)),
conn.State.String(),
conn.UserID,
strconv.FormatUint(conn.Inode, 10),
formatPidProgname(conn.Pid, conn.Exe),
})
}
return results
}
func isListening(conn *netstat.Connection) bool {
tcpListen := strings.HasPrefix(conn.Protocol.Name, "tcp") && conn.State == netstat.TCPListen
udpListen := strings.HasPrefix(conn.Protocol.Name, "udp") && conn.State == netstat.TCPClose
return tcpListen || udpListen
}
func formatPort(port int) string {
if port == 0 {
return "*"
}
return strconv.Itoa(port)
}
func formatPidProgname(pid int, exe string) string {
if pid == 0 {
return "-"
}
_, binary := filepath.Split(exe)
return fmt.Sprintf("%d/%s", pid, binary)
}
func printAligned(table [][]string) {
widths := make([]int, len(table[0]))
for _, row := range table {
for i, cell := range row {
width := len(cell)
if width > widths[i] {
widths[i] = width
}
}
}
for _, row := range table {
for i, cell := range row {
// do not pad last line
if len(row)-1 == i {
fmt.Print(cell)
continue
}
fmt.Printf("%-"+strconv.Itoa(widths[i])+"s ", cell)
}
fmt.Print("\n")
}
}