mirror of
https://github.com/shirou/gopsutil.git
synced 2025-04-26 13:48:59 +08:00
[net]linux: implement processInet().
This commit is contained in:
parent
6c352016d8
commit
32c62b5d48
198
net/net_linux.go
198
net/net_linux.go
@ -199,58 +199,80 @@ func NetFilterCounters() ([]NetFilterStat, error) {
|
|||||||
return stats, nil
|
return stats, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type netConnectionKindType struct {
|
// http://students.mimuw.edu.pl/lxr/source/include/net/tcp_states.h
|
||||||
family int
|
var TCPStatuses = map[string]string{
|
||||||
sockType int
|
"01": "ESTABLISHED",
|
||||||
|
"02": "SYN_SENT",
|
||||||
|
"03": "SYN_RECV",
|
||||||
|
"04": "FIN_WAIT1",
|
||||||
|
"05": "FIN_WAIT2",
|
||||||
|
"06": "TIME_WAIT",
|
||||||
|
"07": "CLOSE",
|
||||||
|
"08": "CLOSE_WAIT",
|
||||||
|
"09": "LAST_ACK",
|
||||||
|
"0A": "LISTEN",
|
||||||
|
"0B": "CLOSING",
|
||||||
}
|
}
|
||||||
|
|
||||||
var KindTCP4 = netConnectionKindType{
|
type netConnectionKindType struct {
|
||||||
|
family uint32
|
||||||
|
sockType uint32
|
||||||
|
f string // file name
|
||||||
|
}
|
||||||
|
|
||||||
|
var kindTCP4 = netConnectionKindType{
|
||||||
family: syscall.AF_INET,
|
family: syscall.AF_INET,
|
||||||
sockType: syscall.SOCK_STREAM,
|
sockType: syscall.SOCK_STREAM,
|
||||||
|
f: "tcp",
|
||||||
}
|
}
|
||||||
var KindTCP6 = netConnectionKindType{
|
var kindTCP6 = netConnectionKindType{
|
||||||
family: syscall.AF_INET6,
|
family: syscall.AF_INET6,
|
||||||
sockType: syscall.SOCK_STREAM,
|
sockType: syscall.SOCK_STREAM,
|
||||||
|
f: "tcp6",
|
||||||
}
|
}
|
||||||
var KindUDP4 = netConnectionKindType{
|
var kindUDP4 = netConnectionKindType{
|
||||||
family: syscall.AF_INET,
|
family: syscall.AF_INET,
|
||||||
sockType: syscall.SOCK_DGRAM,
|
sockType: syscall.SOCK_DGRAM,
|
||||||
|
f: "udp",
|
||||||
}
|
}
|
||||||
var KindUDP6 = netConnectionKindType{
|
var kindUDP6 = netConnectionKindType{
|
||||||
family: syscall.AF_INET6,
|
family: syscall.AF_INET6,
|
||||||
sockType: syscall.SOCK_DGRAM,
|
sockType: syscall.SOCK_DGRAM,
|
||||||
|
f: "udp6",
|
||||||
}
|
}
|
||||||
var KindUNIX = netConnectionKindType{
|
var kindUNIX = netConnectionKindType{
|
||||||
family: syscall.AF_UNIX,
|
family: syscall.AF_UNIX,
|
||||||
|
f: "unix",
|
||||||
}
|
}
|
||||||
|
|
||||||
var netConnectionKindMap = map[string][]netConnectionKindType{
|
var netConnectionKindMap = map[string][]netConnectionKindType{
|
||||||
"all": []netConnectionKindType{KindTCP4, KindTCP6, KindUDP4, KindUDP6, KindUNIX},
|
"all": []netConnectionKindType{kindTCP4, kindTCP6, kindUDP4, kindUDP6, kindUNIX},
|
||||||
"tcp": []netConnectionKindType{KindTCP4, KindTCP6},
|
"tcp": []netConnectionKindType{kindTCP4, kindTCP6},
|
||||||
"tcp4": []netConnectionKindType{KindTCP4},
|
"tcp4": []netConnectionKindType{kindTCP4},
|
||||||
"tcp6": []netConnectionKindType{KindTCP6},
|
"tcp6": []netConnectionKindType{kindTCP6},
|
||||||
"udp": []netConnectionKindType{KindUDP4, KindUDP6},
|
"udp": []netConnectionKindType{kindUDP4, kindUDP6},
|
||||||
"udp4": []netConnectionKindType{KindUDP4},
|
"udp4": []netConnectionKindType{kindUDP4},
|
||||||
"udp6": []netConnectionKindType{KindUDP6},
|
"udp6": []netConnectionKindType{kindUDP6},
|
||||||
"unix": []netConnectionKindType{KindUNIX},
|
"unix": []netConnectionKindType{kindUNIX},
|
||||||
"inet": []netConnectionKindType{KindTCP4, KindTCP6, KindUDP4, KindUDP6},
|
"inet": []netConnectionKindType{kindTCP4, kindTCP6, kindUDP4, kindUDP6},
|
||||||
"inet4": []netConnectionKindType{KindTCP4, KindUDP4},
|
"inet4": []netConnectionKindType{kindTCP4, kindUDP4},
|
||||||
"inet6": []netConnectionKindType{KindTCP6, KindUDP6},
|
"inet6": []netConnectionKindType{kindTCP6, kindUDP6},
|
||||||
}
|
}
|
||||||
|
|
||||||
type inodeMap struct {
|
type inodeMap struct {
|
||||||
pid int32
|
pid int32
|
||||||
fd string
|
fd uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
type bb struct {
|
type connTmp struct {
|
||||||
fd int
|
fd uint32
|
||||||
family int
|
family uint32
|
||||||
sockType int
|
sockType uint32
|
||||||
laddr string
|
laddr Addr
|
||||||
raddr string
|
raddr Addr
|
||||||
status string
|
status string
|
||||||
bound_pid int32
|
pid int32
|
||||||
|
boundPid int32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a list of network connections opened.
|
// Return a list of network connections opened.
|
||||||
@ -271,38 +293,47 @@ func NetConnectionsPid(kind string, pid int32) ([]NetConnectionStat, error) {
|
|||||||
inodes, err = getProcInodesAll(root)
|
inodes, err = getProcInodesAll(root)
|
||||||
} else {
|
} else {
|
||||||
inodes, err = getProcInodes(root, pid)
|
inodes, err = getProcInodes(root, pid)
|
||||||
|
if len(inodes) == 0 {
|
||||||
|
// no connection for the pid
|
||||||
|
return []NetConnectionStat{}, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("cound not get pid(s), %d", pid)
|
return nil, fmt.Errorf("cound not get pid(s), %d", pid)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, t := range tmap {
|
var ret []NetConnectionStat
|
||||||
fmt.Println(t)
|
|
||||||
fmt.Println(inodes)
|
|
||||||
|
|
||||||
|
for _, t := range tmap {
|
||||||
var path string
|
var path string
|
||||||
var ls []string
|
var ls []connTmp
|
||||||
|
path = fmt.Sprintf("%s/net/%s", root, t.f)
|
||||||
switch t.family {
|
switch t.family {
|
||||||
case syscall.AF_INET:
|
case syscall.AF_INET:
|
||||||
path = fmt.Sprintf("%d/net/%s", pid, "tcp")
|
fallthrough
|
||||||
ls, err = processInet(path, t, inodes, pid)
|
|
||||||
case syscall.AF_INET6:
|
case syscall.AF_INET6:
|
||||||
path = fmt.Sprintf("%d/net/%s", pid, "tcp6")
|
|
||||||
ls, err = processInet(path, t, inodes, pid)
|
ls, err = processInet(path, t, inodes, pid)
|
||||||
case syscall.AF_UNIX:
|
case syscall.AF_UNIX:
|
||||||
path = fmt.Sprintf("%d/net/%s", pid, "unix")
|
ls, err = processUnix(path, t, inodes, pid)
|
||||||
ls, err = processInet(path, t, inodes, pid)
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, sss := range ls {
|
for _, c := range ls {
|
||||||
fmt.Println(sss)
|
ret = append(ret, NetConnectionStat{
|
||||||
|
Fd: c.fd,
|
||||||
|
Family: t.family,
|
||||||
|
Type: t.sockType,
|
||||||
|
Laddr: c.laddr,
|
||||||
|
Raddr: c.raddr,
|
||||||
|
Status: c.status,
|
||||||
|
Pid: c.pid,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return []NetConnectionStat{}, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getProcInodes returnes fd of the pid.
|
// getProcInodes returnes fd of the pid.
|
||||||
@ -310,7 +341,6 @@ func getProcInodes(root string, pid int32) (map[string][]inodeMap, error) {
|
|||||||
ret := make(map[string][]inodeMap)
|
ret := make(map[string][]inodeMap)
|
||||||
|
|
||||||
dir := fmt.Sprintf("%s/%d/fd", root, pid)
|
dir := fmt.Sprintf("%s/%d/fd", root, pid)
|
||||||
|
|
||||||
files, err := ioutil.ReadDir(dir)
|
files, err := ioutil.ReadDir(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ret, nil
|
return ret, nil
|
||||||
@ -322,8 +352,6 @@ func getProcInodes(root string, pid int32) (map[string][]inodeMap, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(inodePath)
|
|
||||||
if strings.HasPrefix(inode, "socket:[") {
|
if strings.HasPrefix(inode, "socket:[") {
|
||||||
// the process is using a socket
|
// the process is using a socket
|
||||||
l := len(inode)
|
l := len(inode)
|
||||||
@ -334,10 +362,14 @@ func getProcInodes(root string, pid int32) (map[string][]inodeMap, error) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
ret[inode] = make([]inodeMap, 0)
|
ret[inode] = make([]inodeMap, 0)
|
||||||
}
|
}
|
||||||
|
fd, err := strconv.Atoi(fd.Name())
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
i := inodeMap{
|
i := inodeMap{
|
||||||
pid: pid,
|
pid: pid,
|
||||||
fd: fd.Name(),
|
fd: uint32(fd),
|
||||||
}
|
}
|
||||||
ret[inode] = append(ret[inode], i)
|
ret[inode] = append(ret[inode], i)
|
||||||
}
|
}
|
||||||
@ -390,10 +422,8 @@ func getProcInodesAll(root string) (map[string][]inodeMap, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// TODO: update ret.
|
// TODO: update ret.
|
||||||
|
ret = updateMap(ret, t)
|
||||||
fmt.Println(t)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -401,19 +431,19 @@ func getProcInodesAll(root string) (map[string][]inodeMap, error) {
|
|||||||
// ex:
|
// ex:
|
||||||
// "0500000A:0016" -> "10.0.0.5", 22
|
// "0500000A:0016" -> "10.0.0.5", 22
|
||||||
// "0085002452100113070057A13F025401:0035" -> "2400:8500:1301:1052:a157:7:154:23f", 53
|
// "0085002452100113070057A13F025401:0035" -> "2400:8500:1301:1052:a157:7:154:23f", 53
|
||||||
func decodeAddress(family int, src string) (net.IP, int, error) {
|
func decodeAddress(family uint32, src string) (Addr, error) {
|
||||||
t := strings.Split(src, ":")
|
t := strings.Split(src, ":")
|
||||||
if len(t) != 2 {
|
if len(t) != 2 {
|
||||||
return nil, 0, fmt.Errorf("does not contain port, %s", src)
|
return Addr{}, fmt.Errorf("does not contain port, %s", src)
|
||||||
}
|
}
|
||||||
addr := t[0]
|
addr := t[0]
|
||||||
port, err := strconv.ParseInt("0x"+t[1], 0, 64)
|
port, err := strconv.ParseInt("0x"+t[1], 0, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, fmt.Errorf("invalid port, %s", src)
|
return Addr{}, fmt.Errorf("invalid port, %s", src)
|
||||||
}
|
}
|
||||||
decoded, err := hex.DecodeString(addr)
|
decoded, err := hex.DecodeString(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, fmt.Errorf("decode error:", err)
|
return Addr{}, fmt.Errorf("decode error:", err)
|
||||||
}
|
}
|
||||||
var ip net.IP
|
var ip net.IP
|
||||||
// Assumes this is little_endian
|
// Assumes this is little_endian
|
||||||
@ -422,10 +452,13 @@ func decodeAddress(family int, src string) (net.IP, int, error) {
|
|||||||
} else { // IPv6
|
} else { // IPv6
|
||||||
ip, err = parseIPv6HexString(decoded)
|
ip, err = parseIPv6HexString(decoded)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return Addr{}, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ip, int(port), nil
|
return Addr{
|
||||||
|
IP: ip.String(),
|
||||||
|
Port: uint32(port),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse reverses array of bytes.
|
// Reverse reverses array of bytes.
|
||||||
@ -450,17 +483,18 @@ func parseIPv6HexString(src []byte) (net.IP, error) {
|
|||||||
return net.IP(buf), nil
|
return net.IP(buf), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func processInet(file string, kind netConnectionKindType, inodes map[string][]inodeMap, filterPid int32) ([]string, error) {
|
func processInet(file string, kind netConnectionKindType, inodes map[string][]inodeMap, filterPid int32) ([]connTmp, error) {
|
||||||
|
|
||||||
if strings.HasSuffix(file, "6") && !common.PathExists(file) {
|
if strings.HasSuffix(file, "6") && !common.PathExists(file) {
|
||||||
// IPv6 not supported, return empty.
|
// IPv6 not supported, return empty.
|
||||||
return []string{}, nil
|
return []connTmp{}, nil
|
||||||
}
|
}
|
||||||
lines, err := common.ReadLines(file)
|
lines, err := common.ReadLines(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// skip first line
|
// skip first line
|
||||||
|
var ret []connTmp
|
||||||
for _, line := range lines[1:] {
|
for _, line := range lines[1:] {
|
||||||
l := strings.Fields(line)
|
l := strings.Fields(line)
|
||||||
if len(l) < 10 {
|
if len(l) < 10 {
|
||||||
@ -469,20 +503,58 @@ func processInet(file string, kind netConnectionKindType, inodes map[string][]in
|
|||||||
laddr := l[1]
|
laddr := l[1]
|
||||||
raddr := l[2]
|
raddr := l[2]
|
||||||
status := l[3]
|
status := l[3]
|
||||||
inode, err := strconv.Atoi(l[9])
|
inode := l[9]
|
||||||
|
pid := int32(0)
|
||||||
|
fd := uint32(0)
|
||||||
|
i, exists := inodes[inode]
|
||||||
|
if exists {
|
||||||
|
pid = i[0].pid
|
||||||
|
fd = i[0].fd
|
||||||
|
}
|
||||||
|
if filterPid > 0 && filterPid != pid {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if kind.sockType == syscall.SOCK_STREAM {
|
||||||
|
status = TCPStatuses[status]
|
||||||
|
} else {
|
||||||
|
status = "NONE"
|
||||||
|
}
|
||||||
|
la, err := decodeAddress(kind.family, laddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fmt.Println(laddr)
|
ra, err := decodeAddress(kind.family, raddr)
|
||||||
fmt.Println(raddr)
|
if err != nil {
|
||||||
fmt.Println(status)
|
continue
|
||||||
fmt.Println(inode)
|
}
|
||||||
|
|
||||||
|
ret = append(ret, connTmp{
|
||||||
|
fd: fd,
|
||||||
|
family: kind.family,
|
||||||
|
sockType: kind.sockType,
|
||||||
|
laddr: la,
|
||||||
|
raddr: ra,
|
||||||
|
status: status,
|
||||||
|
pid: pid,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func processUnix(file string, kind netConnectionKindType, inodes map[string][]inodeMap, filterPid int32) ([]string, error) {
|
func processUnix(file string, kind netConnectionKindType, inodes map[string][]inodeMap, filterPid int32) ([]connTmp, error) {
|
||||||
|
|
||||||
return nil, nil
|
return []connTmp{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateMap(src map[string][]inodeMap, add map[string][]inodeMap) map[string][]inodeMap {
|
||||||
|
for key, value := range add {
|
||||||
|
a, exists := src[key]
|
||||||
|
if !exists {
|
||||||
|
src[key] = value
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
src[key] = append(a, value...)
|
||||||
|
}
|
||||||
|
return src
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package net
|
package net
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -11,14 +10,12 @@ import (
|
|||||||
|
|
||||||
func TestGetProcInodes(t *testing.T) {
|
func TestGetProcInodes(t *testing.T) {
|
||||||
root := common.HostProc("")
|
root := common.HostProc("")
|
||||||
|
// checkPid := os.Getpid() // process.test
|
||||||
|
checkPid := 13378
|
||||||
|
|
||||||
// /proc/19957/fd
|
v, err := getProcInodes(root, int32(checkPid))
|
||||||
|
assert.Nil(t, err)
|
||||||
v, err := getProcInodes(root, 19957)
|
assert.NotEmpty(t, v)
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println(v)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type AddrTest struct {
|
type AddrTest struct {
|
||||||
@ -59,13 +56,13 @@ func TestDecodeAddress(t *testing.T) {
|
|||||||
if len(src) > 13 {
|
if len(src) > 13 {
|
||||||
family = syscall.AF_INET6
|
family = syscall.AF_INET6
|
||||||
}
|
}
|
||||||
ip, port, err := decodeAddress(family, src)
|
addr, err := decodeAddress(uint32(family), src)
|
||||||
if dst.Error {
|
if dst.Error {
|
||||||
assert.NotNil(err, src)
|
assert.NotNil(err, src)
|
||||||
} else {
|
} else {
|
||||||
assert.Nil(err, src)
|
assert.Nil(err, src)
|
||||||
assert.Equal(dst.IP, ip.String(), src)
|
assert.Equal(dst.IP, addr.IP, src)
|
||||||
assert.Equal(dst.Port, port, src)
|
assert.Equal(dst.Port, int(addr.Port), src)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user