mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-25 19:15:34 +00:00
e32e5c0d0c
This PR parameterizes receiving loopback updates from the portlist package. Callers can now include services bound to localhost if they want. Note that this option is off by default still. Fixes #8171 Signed-off-by: Marwan Sulaiman <marwan@tailscale.com>
104 lines
2.0 KiB
Go
104 lines
2.0 KiB
Go
// Copyright (c) Tailscale Inc & AUTHORS
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package portlist
|
|
|
|
import (
|
|
"time"
|
|
|
|
"tailscale.com/net/netstat"
|
|
)
|
|
|
|
func init() {
|
|
newOSImpl = newWindowsImpl
|
|
// The portlist poller used to fork on Windows, which is insanely expensive,
|
|
// so historically we only did this every 5 seconds on Windows. Maybe we
|
|
// could reduce it down to 1 seconds like Linux, but nobody's benchmarked as
|
|
// of 2022-11-04.
|
|
pollInterval = 5 * time.Second
|
|
}
|
|
|
|
type famPort struct {
|
|
proto string
|
|
port uint16
|
|
pid uint32
|
|
}
|
|
|
|
type windowsImpl struct {
|
|
known map[famPort]*portMeta // inode string => metadata
|
|
includeLocalhost bool
|
|
}
|
|
|
|
type portMeta struct {
|
|
port Port
|
|
keep bool
|
|
}
|
|
|
|
func newWindowsImpl(includeLocalhost bool) osImpl {
|
|
return &windowsImpl{
|
|
known: map[famPort]*portMeta{},
|
|
includeLocalhost: includeLocalhost,
|
|
}
|
|
}
|
|
|
|
func (*windowsImpl) Close() error { return nil }
|
|
|
|
func (im *windowsImpl) AppendListeningPorts(base []Port) ([]Port, error) {
|
|
// TODO(bradfitz): netstat.Get makes a bunch of garbage. Add an Append-style
|
|
// API to that package instead/additionally.
|
|
tab, err := netstat.Get()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, pm := range im.known {
|
|
pm.keep = false
|
|
}
|
|
|
|
ret := base
|
|
for _, e := range tab.Entries {
|
|
if e.State != "LISTEN" {
|
|
continue
|
|
}
|
|
if !im.includeLocalhost && !e.Local.Addr().IsUnspecified() {
|
|
continue
|
|
}
|
|
fp := famPort{
|
|
proto: "tcp", // TODO(bradfitz): UDP too; add to netstat
|
|
port: e.Local.Port(),
|
|
pid: uint32(e.Pid),
|
|
}
|
|
pm, ok := im.known[fp]
|
|
if ok {
|
|
pm.keep = true
|
|
continue
|
|
}
|
|
var process string
|
|
if e.OSMetadata != nil {
|
|
if module, err := e.OSMetadata.GetModule(); err == nil {
|
|
process = module
|
|
}
|
|
}
|
|
pm = &portMeta{
|
|
keep: true,
|
|
port: Port{
|
|
Proto: "tcp",
|
|
Port: e.Local.Port(),
|
|
Process: process,
|
|
Pid: e.Pid,
|
|
},
|
|
}
|
|
im.known[fp] = pm
|
|
}
|
|
|
|
for k, m := range im.known {
|
|
if !m.keep {
|
|
delete(im.known, k)
|
|
continue
|
|
}
|
|
ret = append(ret, m.port)
|
|
}
|
|
|
|
return sortAndDedup(ret), nil
|
|
}
|