...

Source file src/github.com/shirou/gopsutil/net/net_unix.go

Documentation: github.com/shirou/gopsutil/net

     1  // +build freebsd darwin
     2  
     3  package net
     4  
     5  import (
     6  	"context"
     7  	"fmt"
     8  	"net"
     9  	"strconv"
    10  	"strings"
    11  	"syscall"
    12  
    13  	"github.com/shirou/gopsutil/internal/common"
    14  )
    15  
    16  // Return a list of network connections opened.
    17  func Connections(kind string) ([]ConnectionStat, error) {
    18  	return ConnectionsWithContext(context.Background(), kind)
    19  }
    20  
    21  func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
    22  	return ConnectionsPid(kind, 0)
    23  }
    24  
    25  // Return a list of network connections opened returning at most `max`
    26  // connections for each running process.
    27  func ConnectionsMax(kind string, max int) ([]ConnectionStat, error) {
    28  	return ConnectionsMaxWithContext(context.Background(), kind, max)
    29  }
    30  
    31  func ConnectionsMaxWithContext(ctx context.Context, kind string, max int) ([]ConnectionStat, error) {
    32  	return []ConnectionStat{}, common.ErrNotImplementedError
    33  }
    34  
    35  // Return a list of network connections opened by a process.
    36  func ConnectionsPid(kind string, pid int32) ([]ConnectionStat, error) {
    37  	return ConnectionsPidWithContext(context.Background(), kind, pid)
    38  }
    39  
    40  func ConnectionsPidWithContext(ctx context.Context, kind string, pid int32) ([]ConnectionStat, error) {
    41  	var ret []ConnectionStat
    42  
    43  	args := []string{"-i"}
    44  	switch strings.ToLower(kind) {
    45  	default:
    46  		fallthrough
    47  	case "":
    48  		fallthrough
    49  	case "all":
    50  		fallthrough
    51  	case "inet":
    52  		args = append(args, "tcp", "-i", "udp")
    53  	case "inet4":
    54  		args = append(args, "4")
    55  	case "inet6":
    56  		args = append(args, "6")
    57  	case "tcp":
    58  		args = append(args, "tcp")
    59  	case "tcp4":
    60  		args = append(args, "4tcp")
    61  	case "tcp6":
    62  		args = append(args, "6tcp")
    63  	case "udp":
    64  		args = append(args, "udp")
    65  	case "udp4":
    66  		args = append(args, "4udp")
    67  	case "udp6":
    68  		args = append(args, "6udp")
    69  	case "unix":
    70  		args = []string{"-U"}
    71  	}
    72  
    73  	r, err := common.CallLsofWithContext(ctx, invoke, pid, args...)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  	for _, rr := range r {
    78  		if strings.HasPrefix(rr, "COMMAND") {
    79  			continue
    80  		}
    81  		n, err := parseNetLine(rr)
    82  		if err != nil {
    83  
    84  			continue
    85  		}
    86  
    87  		ret = append(ret, n)
    88  	}
    89  
    90  	return ret, nil
    91  }
    92  
    93  var constMap = map[string]int{
    94  	"unix": syscall.AF_UNIX,
    95  	"TCP":  syscall.SOCK_STREAM,
    96  	"UDP":  syscall.SOCK_DGRAM,
    97  	"IPv4": syscall.AF_INET,
    98  	"IPv6": syscall.AF_INET6,
    99  }
   100  
   101  func parseNetLine(line string) (ConnectionStat, error) {
   102  	f := strings.Fields(line)
   103  	if len(f) < 8 {
   104  		return ConnectionStat{}, fmt.Errorf("wrong line,%s", line)
   105  	}
   106  
   107  	if len(f) == 8 {
   108  		f = append(f, f[7])
   109  		f[7] = "unix"
   110  	}
   111  
   112  	pid, err := strconv.Atoi(f[1])
   113  	if err != nil {
   114  		return ConnectionStat{}, err
   115  	}
   116  	fd, err := strconv.Atoi(strings.Trim(f[3], "u"))
   117  	if err != nil {
   118  		return ConnectionStat{}, fmt.Errorf("unknown fd, %s", f[3])
   119  	}
   120  	netFamily, ok := constMap[f[4]]
   121  	if !ok {
   122  		return ConnectionStat{}, fmt.Errorf("unknown family, %s", f[4])
   123  	}
   124  	netType, ok := constMap[f[7]]
   125  	if !ok {
   126  		return ConnectionStat{}, fmt.Errorf("unknown type, %s", f[7])
   127  	}
   128  
   129  	var laddr, raddr Addr
   130  	if f[7] == "unix" {
   131  		laddr.IP = f[8]
   132  	} else {
   133  		laddr, raddr, err = parseNetAddr(f[8])
   134  		if err != nil {
   135  			return ConnectionStat{}, fmt.Errorf("failed to parse netaddr, %s", f[8])
   136  		}
   137  	}
   138  
   139  	n := ConnectionStat{
   140  		Fd:     uint32(fd),
   141  		Family: uint32(netFamily),
   142  		Type:   uint32(netType),
   143  		Laddr:  laddr,
   144  		Raddr:  raddr,
   145  		Pid:    int32(pid),
   146  	}
   147  	if len(f) == 10 {
   148  		n.Status = strings.Trim(f[9], "()")
   149  	}
   150  
   151  	return n, nil
   152  }
   153  
   154  func parseNetAddr(line string) (laddr Addr, raddr Addr, err error) {
   155  	parse := func(l string) (Addr, error) {
   156  		host, port, err := net.SplitHostPort(l)
   157  		if err != nil {
   158  			return Addr{}, fmt.Errorf("wrong addr, %s", l)
   159  		}
   160  		lport, err := strconv.Atoi(port)
   161  		if err != nil {
   162  			return Addr{}, err
   163  		}
   164  		return Addr{IP: host, Port: uint32(lport)}, nil
   165  	}
   166  
   167  	addrs := strings.Split(line, "->")
   168  	if len(addrs) == 0 {
   169  		return laddr, raddr, fmt.Errorf("wrong netaddr, %s", line)
   170  	}
   171  	laddr, err = parse(addrs[0])
   172  	if len(addrs) == 2 { // remote addr exists
   173  		raddr, err = parse(addrs[1])
   174  		if err != nil {
   175  			return laddr, raddr, err
   176  		}
   177  	}
   178  
   179  	return laddr, raddr, err
   180  }
   181  
   182  // Return up to `max` network connections opened by a process.
   183  func ConnectionsPidMax(kind string, pid int32, max int) ([]ConnectionStat, error) {
   184  	return ConnectionsPidMaxWithContext(context.Background(), kind, pid, max)
   185  }
   186  
   187  func ConnectionsPidMaxWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
   188  	return []ConnectionStat{}, common.ErrNotImplementedError
   189  }
   190  
   191  // Return a list of network connections opened, omitting `Uids`.
   192  // WithoutUids functions are reliant on implementation details. They may be altered to be an alias for Connections or be
   193  // removed from the API in the future.
   194  func ConnectionsWithoutUids(kind string) ([]ConnectionStat, error) {
   195  	return ConnectionsWithoutUidsWithContext(context.Background(), kind)
   196  }
   197  
   198  func ConnectionsWithoutUidsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
   199  	return ConnectionsMaxWithoutUidsWithContext(ctx, kind, 0)
   200  }
   201  
   202  func ConnectionsMaxWithoutUidsWithContext(ctx context.Context, kind string, max int) ([]ConnectionStat, error) {
   203  	return ConnectionsPidMaxWithoutUidsWithContext(ctx, kind, 0, max)
   204  }
   205  
   206  func ConnectionsPidWithoutUids(kind string, pid int32) ([]ConnectionStat, error) {
   207  	return ConnectionsPidWithoutUidsWithContext(context.Background(), kind, pid)
   208  }
   209  
   210  func ConnectionsPidWithoutUidsWithContext(ctx context.Context, kind string, pid int32) ([]ConnectionStat, error) {
   211  	return ConnectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, 0)
   212  }
   213  
   214  func ConnectionsPidMaxWithoutUids(kind string, pid int32, max int) ([]ConnectionStat, error) {
   215  	return ConnectionsPidMaxWithoutUidsWithContext(context.Background(), kind, pid, max)
   216  }
   217  
   218  func ConnectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
   219  	return connectionsPidMaxWithoutUidsWithContext(ctx, kind, pid, max)
   220  }
   221  
   222  func connectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) {
   223  	return []ConnectionStat{}, common.ErrNotImplementedError
   224  }
   225  

View as plain text