Add netstat applet

pull/2/head
James Mills 1 week ago
parent 6dc516ec0c
commit aee9aba7c8
Signed by: prologic
GPG Key ID: AC4C014F1440EBD6
  1. 1
      cmd/coreutils/applets.go
  2. 1
      go.mod
  3. 6
      go.sum
  4. 163
      internal/applets/netstat/netstat.go

@ -51,6 +51,7 @@ import (
_ "git.mills.io/prologic/gonix/internal/applets/mknod"
_ "git.mills.io/prologic/gonix/internal/applets/mount"
_ "git.mills.io/prologic/gonix/internal/applets/mv"
_ "git.mills.io/prologic/gonix/internal/applets/netstat"
_ "git.mills.io/prologic/gonix/internal/applets/nl"
_ "git.mills.io/prologic/gonix/internal/applets/nproc"
_ "git.mills.io/prologic/gonix/internal/applets/paste"

@ -4,6 +4,7 @@ go 1.18
require (
git.mills.io/prologic/ed v0.0.0-20220702183135-b73a4a53ca81
git.mills.io/prologic/go-netstat v0.0.0-20220805050011-f5d3cd86b10f
git.mills.io/prologic/vi v0.0.0-20220702193316-2ab87662fd20
github.com/Masterminds/sprig/v3 v3.2.2
github.com/NicoNex/tau v1.1.4-0.20220802172017-0290336f402c

@ -2,6 +2,8 @@ git.mills.io/prologic/ed v0.0.0-20220702183135-b73a4a53ca81 h1:tsMYLFAuBrIb6BHaQ
git.mills.io/prologic/ed v0.0.0-20220702183135-b73a4a53ca81/go.mod h1:ulFHRZfxb6vptGXXBylKVVcxyYdCf57QoxqztK0/76M=
git.mills.io/prologic/go-diskfs v0.0.0-20220716064315-a011c6ff1c6f h1:Q6ZXvUTqivSlX9Dzs3A5aAALPlXC3J3Kc1nuOy3Gla8=
git.mills.io/prologic/go-diskfs v0.0.0-20220716064315-a011c6ff1c6f/go.mod h1:Tl2oy/U2iEwthjUoTKYhca96sA38nSRuxPsrVk+YJZo=
git.mills.io/prologic/go-netstat v0.0.0-20220805050011-f5d3cd86b10f h1:dqbdoYgow5KpfCBLcLQAEDv0EI5/KvOQRkWuZ0d/7k4=
git.mills.io/prologic/go-netstat v0.0.0-20220805050011-f5d3cd86b10f/go.mod h1:fyjePFxzXKoRMpkzJ7z6RKvZwDgwuWFKa2mKZA+pPD4=
git.mills.io/prologic/vi v0.0.0-20220702193316-2ab87662fd20 h1:enEbtRq+xGhNoemnG3q6uKceKQTrXyTPC+W4/xKxsek=
git.mills.io/prologic/vi v0.0.0-20220702193316-2ab87662fd20/go.mod h1:UXfoRKVn/elxYO8DBRSGWw9vgpiy/mrZDC1KmX93hdE=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
@ -10,10 +12,6 @@ github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030I
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8=
github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
github.com/NicoNex/tau v1.1.3 h1:X+hcVg7G2QLbdPjI28DBUe+EhROy/EVLxg4Qq5n/qO8=
github.com/NicoNex/tau v1.1.3/go.mod h1:La7NDgLNmdhA+1Y0/1sr1hpQJrDPbcH91ss1KVzdK64=
github.com/NicoNex/tau v1.1.4-0.20220802135910-45699938930c h1:my+hffgWEUrdk7YAmwLH2hxCs7P/OCuuMLluzdXMgZg=
github.com/NicoNex/tau v1.1.4-0.20220802135910-45699938930c/go.mod h1:La7NDgLNmdhA+1Y0/1sr1hpQJrDPbcH91ss1KVzdK64=
github.com/NicoNex/tau v1.1.4-0.20220802172017-0290336f402c h1:gOmS6sp0PFngDdd71Su9XSsSwinSYEGfAnV4oODoKes=
github.com/NicoNex/tau v1.1.4-0.20220802172017-0290336f402c/go.mod h1:La7NDgLNmdhA+1Y0/1sr1hpQJrDPbcH91ss1KVzdK64=
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=

@ -0,0 +1,163 @@
package netstat
import (
"flag"
"fmt"
"io"
"net"
"git.mills.io/prologic/go-netstat"
"git.mills.io/prologic/gonix/internal/applets"
)
const binaryName = "netstat"
const helpText = `
Display networking information
`
const (
protoIPv4 = 0x01
protoIPv6 = 0x02
)
func init() {
applets.Register(binaryName, Main)
}
type Option struct {
helpFlag bool
udpFlag bool
tcpFlag bool
listeningFlag bool
allFlag bool
resolveFlag bool
ipv4Flag bool
ipv6Flag bool
}
func NewFlagSet() (*flag.FlagSet, *Option) {
ret := flag.NewFlagSet(binaryName, flag.ExitOnError)
ret.Usage = func() {
fmt.Printf("Usage: %s [OPTIONS] ...\n", binaryName)
fmt.Printf("%s\n", helpText)
ret.PrintDefaults()
}
var opt Option
ret.BoolVar(&opt.helpFlag, "help", false, "show this message")
ret.BoolVar(&opt.udpFlag, "u", false, "display UDP sockets")
ret.BoolVar(&opt.tcpFlag, "t", false, "display TCP sockets")
ret.BoolVar(&opt.listeningFlag, "l", false, "display only listening sockets")
ret.BoolVar(&opt.allFlag, "a", false, "display both listening and non-listening sockets")
ret.BoolVar(&opt.resolveFlag, "r", false, "lookup symbolic names for host addresses")
ret.BoolVar(&opt.ipv4Flag, "4", false, "display only IPv4 sockets")
ret.BoolVar(&opt.ipv6Flag, "6", false, "display only IPv6 sockets")
return ret, &opt
}
func Main(stdout io.Writer, args []string) error {
flagSet, opt := NewFlagSet()
flagSet.Parse(args)
if opt.helpFlag {
flagSet.Usage()
return nil
}
return Netstat(stdout, flagSet.Args(), opt)
}
func Netstat(w io.Writer, args []string, opt *Option) error {
var proto uint
if opt.ipv4Flag {
proto |= protoIPv4
}
if opt.ipv6Flag {
proto |= protoIPv6
}
if proto == 0x00 {
proto = protoIPv4 | protoIPv6
}
fmt.Printf("Proto %-23s %-23s %-12s %-16s\n", "Local Addr", "Foreign Addr", "State", "PID/Program name")
if opt.udpFlag {
if proto&protoIPv4 == protoIPv4 {
tabs, err := netstat.UDPSocks(netstat.NoopFilter)
if err == nil {
displaySockInfo(w, "udp", tabs, opt.resolveFlag)
}
}
if proto&protoIPv6 == protoIPv6 {
tabs, err := netstat.UDP6Socks(netstat.NoopFilter)
if err == nil {
displaySockInfo(w, "udp6", tabs, opt.resolveFlag)
}
}
} else {
opt.tcpFlag = true
}
if opt.tcpFlag {
var fn netstat.AcceptFn
switch {
case opt.allFlag:
fn = func(*netstat.SockTabEntry) bool { return true }
case opt.listeningFlag:
fn = func(s *netstat.SockTabEntry) bool {
return s.State == netstat.Listen
}
default:
fn = func(s *netstat.SockTabEntry) bool {
return s.State != netstat.Listen
}
}
if proto&protoIPv4 == protoIPv4 {
tabs, err := netstat.TCPSocks(fn)
if err == nil {
displaySockInfo(w, "tcp", tabs, opt.resolveFlag)
}
}
if proto&protoIPv6 == protoIPv6 {
tabs, err := netstat.TCP6Socks(fn)
if err == nil {
displaySockInfo(w, "tcp6", tabs, opt.resolveFlag)
}
}
}
return nil
}
func displaySockInfo(w io.Writer, proto string, s []netstat.SockTabEntry, resolve bool) {
lookup := func(skaddr *netstat.SockAddr) string {
const IPv4Strlen = 17
addr := skaddr.IP.String()
if resolve {
names, err := net.LookupAddr(addr)
if err == nil && len(names) > 0 {
addr = names[0]
}
}
if len(addr) > IPv4Strlen {
addr = addr[:IPv4Strlen]
}
return fmt.Sprintf("%s:%d", addr, skaddr.Port)
}
for _, e := range s {
p := ""
if e.Process != nil {
p = e.Process.String()
}
saddr := lookup(e.LocalAddr)
daddr := lookup(e.RemoteAddr)
fmt.Fprintf(w, "%-5s %-23.23s %-23.23s %-12s %-16s\n", proto, saddr, daddr, e.State, p)
}
}
Loading…
Cancel
Save