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