Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/rex/socket/comm/local.rb
Original file line number Diff line number Diff line change
Expand Up @@ -273,10 +273,11 @@ def self.create_by_type(param, type, proto = 0)
end

sock.bind(Rex::Socket.to_sockaddr(ip, param.localport))

rescue ::Errno::EADDRNOTAVAIL,::Errno::EADDRINUSE
sock.close
raise Rex::BindFailed.new(param.localhost, param.localport), caller
else
param.localport = sock.local_address.ip_port
end
end

Expand Down
1 change: 1 addition & 0 deletions lib/rex/socket/proxies.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# -*- coding: binary -*-
require 'uri'

module Rex
module Socket
Expand Down
39 changes: 39 additions & 0 deletions spec/rex/socket/comm/local_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
let(:proto) { ::Socket::IPPROTO_TCP }
let(:params) { Rex::Socket::Parameters.new({ 'PeerHost' => '192.0.2.1', 'PeerPort' => 1234 }) }
let(:sock) { RSpec::Mocks::Double.new('socket') }
let(:local_address) { RSpec::Mocks::Double.new('local address', ip_port: 49152) }

before(:each) do
allow(Rex::Socket).to receive(:support_ipv6?).with(no_args).and_return(true)
allow(::Socket).to receive(:new).with(any_args).and_return(sock)
allow(sock).to receive(:setsockopt).with(any_args)
allow(sock).to receive(:bind).with(any_args)
allow(sock).to receive(:connect).with(any_args).and_return(nil)
allow(sock).to receive(:local_address).with(no_args).and_return(local_address)
end

it 'creates an IPv4 socket' do
Expand Down Expand Up @@ -108,6 +110,43 @@
end
end

describe 'LocalPort 0 assignment' do
context 'when creating a TCP server bound to port 0' do
it 'updates localport to the OS-assigned port' do
params = Rex::Socket::Parameters.new(
'Proto' => 'tcp',
'Server' => true,
'LocalHost' => '127.0.0.1',
'LocalPort' => 0
)
sock = described_class.create(params)
begin
expect(sock.localport).to be > 0
expect(sock.localport).to eq(sock.local_address.ip_port)
ensure
sock.close
end
end
end

context 'when creating a UDP socket bound to port 0' do
it 'updates localport to the OS-assigned port' do
params = Rex::Socket::Parameters.new(
'Proto' => 'udp',
'LocalHost' => '127.0.0.1',
'LocalPort' => 0
)
sock = described_class.create(params)
begin
expect(sock.localport).to be > 0
expect(sock.localport).to eq(sock.local_address.ip_port)
ensure
sock.close
end
end
end
end

describe 'Interface option' do
context 'when Interface is set and a proxy is also configured' do
it 'raises Rex::BindFailed before creating a socket' do
Expand Down
Loading