summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/ports
diff options
context:
space:
mode:
authorTamir Duberstein <tamird@google.com>2018-09-17 20:42:48 -0700
committerShentubot <shentubot@google.com>2018-09-17 20:44:04 -0700
commitd6409b6564d6f908a217709010df2276497b264b (patch)
treeeef606f06646507d0fbfdba60d48ffc3ff46b715 /pkg/tcpip/ports
parentbb88c187c5457df14fa78e5e6b6f48cbc90fb489 (diff)
Prevent TCP connect from picking bound ports
PiperOrigin-RevId: 213387851 Change-Id: Icc6850761bc11afd0525f34863acd77584155140
Diffstat (limited to 'pkg/tcpip/ports')
-rw-r--r--pkg/tcpip/ports/ports.go46
-rw-r--r--pkg/tcpip/ports/ports_test.go10
2 files changed, 35 insertions, 21 deletions
diff --git a/pkg/tcpip/ports/ports.go b/pkg/tcpip/ports/ports.go
index db7371efb..4e24efddb 100644
--- a/pkg/tcpip/ports/ports.go
+++ b/pkg/tcpip/ports/ports.go
@@ -24,8 +24,8 @@ import (
)
const (
- // firstEphemeral is the first ephemeral port.
- firstEphemeral uint16 = 16000
+ // FirstEphemeral is the first ephemeral port.
+ FirstEphemeral = 16000
anyIPAddress tcpip.Address = ""
)
@@ -73,11 +73,11 @@ func NewPortManager() *PortManager {
// is suitable for its needs, and stopping when a port is found or an error
// occurs.
func (s *PortManager) PickEphemeralPort(testPort func(p uint16) (bool, *tcpip.Error)) (port uint16, err *tcpip.Error) {
- count := uint16(math.MaxUint16 - firstEphemeral + 1)
+ count := uint16(math.MaxUint16 - FirstEphemeral + 1)
offset := uint16(rand.Int31n(int32(count)))
for i := uint16(0); i < count; i++ {
- port = firstEphemeral + (offset+i)%count
+ port = FirstEphemeral + (offset+i)%count
ok, err := testPort(port)
if err != nil {
return 0, err
@@ -91,6 +91,25 @@ func (s *PortManager) PickEphemeralPort(testPort func(p uint16) (bool, *tcpip.Er
return 0, tcpip.ErrNoPortAvailable
}
+// IsPortAvailable tests if the given port is available on all given protocols.
+func (s *PortManager) IsPortAvailable(networks []tcpip.NetworkProtocolNumber, transport tcpip.TransportProtocolNumber, addr tcpip.Address, port uint16) bool {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ return s.isPortAvailableLocked(networks, transport, addr, port)
+}
+
+func (s *PortManager) isPortAvailableLocked(networks []tcpip.NetworkProtocolNumber, transport tcpip.TransportProtocolNumber, addr tcpip.Address, port uint16) bool {
+ for _, network := range networks {
+ desc := portDescriptor{network, transport, port}
+ if addrs, ok := s.allocatedPorts[desc]; ok {
+ if !addrs.isAvailable(addr) {
+ return false
+ }
+ }
+ }
+ return true
+}
+
// ReservePort marks a port/IP combination as reserved so that it cannot be
// reserved by another endpoint. If port is zero, ReservePort will search for
// an unreserved ephemeral port and reserve it, returning its value in the
@@ -116,14 +135,8 @@ func (s *PortManager) ReservePort(networks []tcpip.NetworkProtocolNumber, transp
// reserveSpecificPort tries to reserve the given port on all given protocols.
func (s *PortManager) reserveSpecificPort(networks []tcpip.NetworkProtocolNumber, transport tcpip.TransportProtocolNumber, addr tcpip.Address, port uint16) bool {
- // Check that the port is available on all network protocols.
- for _, network := range networks {
- desc := portDescriptor{network, transport, port}
- if addrs, ok := s.allocatedPorts[desc]; ok {
- if !addrs.isAvailable(addr) {
- return false
- }
- }
+ if !s.isPortAvailableLocked(networks, transport, addr, port) {
+ return false
}
// Reserve port on all network protocols.
@@ -148,10 +161,11 @@ func (s *PortManager) ReleasePort(networks []tcpip.NetworkProtocolNumber, transp
for _, network := range networks {
desc := portDescriptor{network, transport, port}
- m := s.allocatedPorts[desc]
- delete(m, addr)
- if len(m) == 0 {
- delete(s.allocatedPorts, desc)
+ if m, ok := s.allocatedPorts[desc]; ok {
+ delete(m, addr)
+ if len(m) == 0 {
+ delete(s.allocatedPorts, desc)
+ }
}
}
}
diff --git a/pkg/tcpip/ports/ports_test.go b/pkg/tcpip/ports/ports_test.go
index 825d5d314..4ab6a1fa2 100644
--- a/pkg/tcpip/ports/ports_test.go
+++ b/pkg/tcpip/ports/ports_test.go
@@ -78,8 +78,8 @@ func TestPortReservation(t *testing.T) {
if err != test.want {
t.Fatalf("ReservePort(.., .., %s, %d) = %v, want %v", test.ip, test.port, err, test.want)
}
- if test.port == 0 && (gotPort == 0 || gotPort < firstEphemeral) {
- t.Fatalf("ReservePort(.., .., .., 0) = %d, want port number >= %d to be picked", gotPort, firstEphemeral)
+ if test.port == 0 && (gotPort == 0 || gotPort < FirstEphemeral) {
+ t.Fatalf("ReservePort(.., .., .., 0) = %d, want port number >= %d to be picked", gotPort, FirstEphemeral)
}
}
@@ -118,17 +118,17 @@ func TestPickEphemeralPort(t *testing.T) {
{
name: "only-port-16042-available",
f: func(port uint16) (bool, *tcpip.Error) {
- if port == firstEphemeral+42 {
+ if port == FirstEphemeral+42 {
return true, nil
}
return false, nil
},
- wantPort: firstEphemeral + 42,
+ wantPort: FirstEphemeral + 42,
},
{
name: "only-port-under-16000-available",
f: func(port uint16) (bool, *tcpip.Error) {
- if port < firstEphemeral {
+ if port < FirstEphemeral {
return true, nil
}
return false, nil