|
|
|
@ -4,13 +4,18 @@ package net
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
|
|
|
|
"os/exec"
|
|
|
|
|
"regexp"
|
|
|
|
|
"strconv"
|
|
|
|
|
"strings"
|
|
|
|
|
"syscall"
|
|
|
|
|
|
|
|
|
|
"github.com/shirou/gopsutil/internal/common"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var portMatch = regexp.MustCompile(`(.*)\.(\d+)$`)
|
|
|
|
|
|
|
|
|
|
func ParseNetstat(output string, mode string,
|
|
|
|
|
iocs map[string]IOCountersStat) error {
|
|
|
|
|
lines := strings.Split(output, "\n")
|
|
|
|
@ -92,7 +97,7 @@ func ParseNetstat(output string, mode string,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func IOCounters(pernic bool) ([]IOCountersStat, error) {
|
|
|
|
|
netstat, err := exec.LookPath("/usr/bin/netstat")
|
|
|
|
|
netstat, err := exec.LookPath("netstat")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
@ -146,8 +151,141 @@ func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) {
|
|
|
|
|
return nil, errors.New("NetProtoCounters not implemented for openbsd")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func parseNetstatLine(line string) (ConnectionStat, error) {
|
|
|
|
|
f := strings.Fields(line)
|
|
|
|
|
if len(f) < 5 {
|
|
|
|
|
return ConnectionStat{}, fmt.Errorf("wrong line,%s", line)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var netType, netFamily uint32
|
|
|
|
|
switch f[0] {
|
|
|
|
|
case "tcp":
|
|
|
|
|
netType = syscall.SOCK_STREAM
|
|
|
|
|
netFamily = syscall.AF_INET
|
|
|
|
|
case "udp":
|
|
|
|
|
netType = syscall.SOCK_DGRAM
|
|
|
|
|
netFamily = syscall.AF_INET
|
|
|
|
|
case "tcp6":
|
|
|
|
|
netType = syscall.SOCK_STREAM
|
|
|
|
|
netFamily = syscall.AF_INET6
|
|
|
|
|
case "udp6":
|
|
|
|
|
netType = syscall.SOCK_DGRAM
|
|
|
|
|
netFamily = syscall.AF_INET6
|
|
|
|
|
default:
|
|
|
|
|
return ConnectionStat{}, fmt.Errorf("unknown type, %s", f[0])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
laddr, raddr, err := parseNetstatAddr(f[3], f[4], netFamily)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return ConnectionStat{}, fmt.Errorf("failed to parse netaddr, %s %s", f[3], f[4])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
n := ConnectionStat{
|
|
|
|
|
Fd: uint32(0), // not supported
|
|
|
|
|
Family: uint32(netFamily),
|
|
|
|
|
Type: uint32(netType),
|
|
|
|
|
Laddr: laddr,
|
|
|
|
|
Raddr: raddr,
|
|
|
|
|
Pid: int32(0), // not supported
|
|
|
|
|
}
|
|
|
|
|
if len(f) == 6 {
|
|
|
|
|
n.Status = f[5]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return n, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func parseNetstatAddr(local string, remote string, family uint32) (laddr Addr, raddr Addr, err error) {
|
|
|
|
|
parse := func(l string) (Addr, error) {
|
|
|
|
|
matches := portMatch.FindStringSubmatch(l)
|
|
|
|
|
if matches == nil {
|
|
|
|
|
return Addr{}, fmt.Errorf("wrong addr, %s", l)
|
|
|
|
|
}
|
|
|
|
|
host := matches[1]
|
|
|
|
|
port := matches[2]
|
|
|
|
|
if host == "*" {
|
|
|
|
|
switch family {
|
|
|
|
|
case syscall.AF_INET:
|
|
|
|
|
host = "0.0.0.0"
|
|
|
|
|
case syscall.AF_INET6:
|
|
|
|
|
host = "::"
|
|
|
|
|
default:
|
|
|
|
|
return Addr{}, fmt.Errorf("unknown family, %d", family)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
lport, err := strconv.Atoi(port)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return Addr{}, err
|
|
|
|
|
}
|
|
|
|
|
return Addr{IP: host, Port: uint32(lport)}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
laddr, err = parse(local)
|
|
|
|
|
if remote != "*.*" { // remote addr exists
|
|
|
|
|
raddr, err = parse(remote)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return laddr, raddr, err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return laddr, raddr, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Return a list of network connections opened.
|
|
|
|
|
// Not Implemented for OpenBSD
|
|
|
|
|
func Connections(kind string) ([]ConnectionStat, error) {
|
|
|
|
|
return nil, errors.New("Connections not implemented for openbsd")
|
|
|
|
|
var ret []ConnectionStat
|
|
|
|
|
|
|
|
|
|
args := []string{"-na"}
|
|
|
|
|
switch strings.ToLower(kind) {
|
|
|
|
|
default:
|
|
|
|
|
fallthrough
|
|
|
|
|
case "":
|
|
|
|
|
fallthrough
|
|
|
|
|
case "all":
|
|
|
|
|
fallthrough
|
|
|
|
|
case "inet":
|
|
|
|
|
// nothing to add
|
|
|
|
|
case "inet4":
|
|
|
|
|
args = append(args, "-finet")
|
|
|
|
|
case "inet6":
|
|
|
|
|
args = append(args, "-finet6")
|
|
|
|
|
case "tcp":
|
|
|
|
|
args = append(args, "-ptcp")
|
|
|
|
|
case "tcp4":
|
|
|
|
|
args = append(args, "-ptcp", "-finet")
|
|
|
|
|
case "tcp6":
|
|
|
|
|
args = append(args, "-ptcp", "-finet6")
|
|
|
|
|
case "udp":
|
|
|
|
|
args = append(args, "-pudp")
|
|
|
|
|
case "udp4":
|
|
|
|
|
args = append(args, "-pudp", "-finet")
|
|
|
|
|
case "udp6":
|
|
|
|
|
args = append(args, "-pudp", "-finet6")
|
|
|
|
|
case "unix":
|
|
|
|
|
return ret, common.ErrNotImplementedError
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
netstat, err := exec.LookPath("netstat")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
out, err := invoke.Command(netstat, args...)
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
lines := strings.Split(string(out), "\n")
|
|
|
|
|
for _, line := range lines {
|
|
|
|
|
if !(strings.HasPrefix(line, "tcp") || strings.HasPrefix(line, "udp")) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
n, err := parseNetstatLine(line)
|
|
|
|
|
if err != nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = append(ret, n)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret, nil
|
|
|
|
|
}
|
|
|
|
|