| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- // +build freebsd darwin
- package net
- import (
- "context"
- "fmt"
- "net"
- "strconv"
- "strings"
- "syscall"
- "github.com/shirou/gopsutil/internal/common"
- )
- // Return a list of network connections opened.
- func Connections(kind string) ([]ConnectionStat, error) {
- return ConnectionsWithContext(context.Background(), kind)
- }
- func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
- return ConnectionsPid(kind, 0)
- }
- // Return a list of network connections opened returning at most `max`
- // connections for each running process.
- func ConnectionsMax(kind string, max int) ([]ConnectionStat, error) {
- return ConnectionsMaxWithContext(context.Background(), kind, max)
- }
- func ConnectionsMaxWithContext(ctx context.Context, kind string, max int) ([]ConnectionStat, error) {
- return []ConnectionStat{}, common.ErrNotImplementedError
- }
- // Return a list of network connections opened by a process.
- func ConnectionsPid(kind string, pid int32) ([]ConnectionStat, error) {
- return ConnectionsPidWithContext(context.Background(), kind, pid)
- }
- func ConnectionsPidWithContext(ctx context.Context, kind string, pid int32) ([]ConnectionStat, error) {
- var ret []ConnectionStat
- args := []string{"-i"}
- switch strings.ToLower(kind) {
- default:
- fallthrough
- case "":
- fallthrough
- case "all":
- fallthrough
- case "inet":
- args = append(args, "tcp", "-i", "udp")
- case "inet4":
- args = append(args, "4")
- case "inet6":
- args = append(args, "6")
- case "tcp":
- args = append(args, "tcp")
- case "tcp4":
- args = append(args, "4tcp")
- case "tcp6":
- args = append(args, "6tcp")
- case "udp":
- args = append(args, "udp")
- case "udp4":
- args = append(args, "4udp")
- case "udp6":
- args = append(args, "6udp")
- case "unix":
- args = []string{"-U"}
- }
- r, err := common.CallLsofWithContext(ctx, invoke, pid, args...)
- if err != nil {
- return nil, err
- }
- for _, rr := range r {
- if strings.HasPrefix(rr, "COMMAND") {
- continue
- }
- n, err := parseNetLine(rr)
- if err != nil {
- continue
- }
- ret = append(ret, n)
- }
- return ret, nil
- }
- var constMap = map[string]int{
- "unix": syscall.AF_UNIX,
- "TCP": syscall.SOCK_STREAM,
- "UDP": syscall.SOCK_DGRAM,
- "IPv4": syscall.AF_INET,
- "IPv6": syscall.AF_INET6,
- }
- func parseNetLine(line string) (ConnectionStat, error) {
- f := strings.Fields(line)
- if len(f) < 8 {
- return ConnectionStat{}, fmt.Errorf("wrong line,%s", line)
- }
- if len(f) == 8 {
- f = append(f, f[7])
- f[7] = "unix"
- }
- pid, err := strconv.Atoi(f[1])
- if err != nil {
- return ConnectionStat{}, err
- }
- fd, err := strconv.Atoi(strings.Trim(f[3], "u"))
- if err != nil {
- return ConnectionStat{}, fmt.Errorf("unknown fd, %s", f[3])
- }
- netFamily, ok := constMap[f[4]]
- if !ok {
- return ConnectionStat{}, fmt.Errorf("unknown family, %s", f[4])
- }
- netType, ok := constMap[f[7]]
- if !ok {
- return ConnectionStat{}, fmt.Errorf("unknown type, %s", f[7])
- }
- var laddr, raddr Addr
- if f[7] == "unix" {
- laddr.IP = f[8]
- } else {
- laddr, raddr, err = parseNetAddr(f[8])
- if err != nil {
- return ConnectionStat{}, fmt.Errorf("failed to parse netaddr, %s", f[8])
- }
- }
- n := ConnectionStat{
- Fd: uint32(fd),
- Family: uint32(netFamily),
- Type: uint32(netType),
- Laddr: laddr,
- Raddr: raddr,
- Pid: int32(pid),
- }
- if len(f) == 10 {
- n.Status = strings.Trim(f[9], "()")
- }
- return n, nil
- }
- func parseNetAddr(line string) (laddr Addr, raddr Addr, err error) {
- parse := func(l string) (Addr, error) {
- host, port, err := net.SplitHostPort(l)
- if err != nil {
- return Addr{}, fmt.Errorf("wrong addr, %s", l)
- }
- lport, err := strconv.Atoi(port)
- if err != nil {
- return Addr{}, err
- }
- return Addr{IP: host, Port: uint32(lport)}, nil
- }
- addrs := strings.Split(line, "->")
- if len(addrs) == 0 {
- return laddr, raddr, fmt.Errorf("wrong netaddr, %s", line)
- }
- laddr, err = parse(addrs[0])
- if len(addrs) == 2 { // remote addr exists
- raddr, err = parse(addrs[1])
- if err != nil {
- return laddr, raddr, err
- }
- }
- return laddr, raddr, err
- }
- // Return up to `max` network connections opened by a process.
- func ConnectionsPidMax(kind string, pid int32, max int) ([]ConnectionStat, error) {
- return ConnectionsPidMaxWithContext(context.Background(), kind, pid, max)
- }
- func ConnectionsPidMaxWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
- return []ConnectionStat{}, common.ErrNotImplementedError
- }
- // Return a list of network connections opened, omitting `Uids`.
- // WithoutUids functions are reliant on implementation details. They may be altered to be an alias for Connections or be
- // removed from the API in the future.
- func ConnectionsWithoutUids(kind string) ([]ConnectionStat, error) {
- return ConnectionsWithoutUidsWithContext(context.Background(), kind)
- }
- func ConnectionsWithoutUidsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
- return ConnectionsMaxWithoutUidsWithContext(ctx, kind, 0)
- }
- func ConnectionsMaxWithoutUidsWithContext(ctx context.Context, kind string, max int) ([]ConnectionStat, error) {
- return ConnectionsPidMaxWithoutUidsWithContext(ctx, kind, 0, max)
- }
- func ConnectionsPidWithoutUids(kind string, pid int32) ([]ConnectionStat, error) {
- return ConnectionsPidWithoutUidsWithContext(context.Background(), kind, pid)
- }
- func ConnectionsPidWithoutUidsWithContext(ctx context.Context, kind string, pid int32) ([]ConnectionStat, error) {
- return ConnectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, 0)
- }
- func ConnectionsPidMaxWithoutUids(kind string, pid int32, max int) ([]ConnectionStat, error) {
- return ConnectionsPidMaxWithoutUidsWithContext(context.Background(), kind, pid, max)
- }
- func ConnectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
- return connectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, max)
- }
- func connectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
- return []ConnectionStat{}, common.ErrNotImplementedError
- }
|