diff --git a/src/control.c b/src/control.c index 3a9802c..055f479 100644 --- a/src/control.c +++ b/src/control.c @@ -134,6 +134,7 @@ int control_accept( struct control * control ) FD_ZERO( &fds ); FD_SET( control->control_fd, &fds ); self_pipe_fd_set( control->close_signal, &fds ); + debug("Control thread selecting"); FATAL_UNLESS( 0 < select( FD_SETSIZE, &fds, NULL, NULL, NULL ), "Control select failed." ); @@ -398,49 +399,44 @@ void control_cleanup(struct control_client* client, void control_respond(struct control_client * client) { char **lines = NULL; - int finished=0; - + error_set_handler((cleanup_handler*) control_cleanup, client); - - while (!finished) { - int i, linesc; - linesc = read_lines_until_blankline(client->socket, 256, &lines); - - if (linesc < 1) - { - write(client->socket, "9: missing command\n", 19); - finished = 1; - /* ignore failure */ - } - else if (strcmp(lines[0], "acl") == 0) { - info("acl command received" ); - if (control_acl(client, linesc-1, lines+1) < 0) { - finished = 1; - } - } - else if (strcmp(lines[0], "mirror") == 0) { - info("mirror command received" ); - if (control_mirror(client, linesc-1, lines+1) < 0) { - finished = 1; - } - } - else if (strcmp(lines[0], "status") == 0) { - info("status command received" ); - if (control_status(client, linesc-1, lines+1) < 0) { - finished = 1; - } - } - else { - write(client->socket, "10: unknown command\n", 23); - finished = 1; - } - - for (i=0; isocket, 256, &lines); + + if (linesc < 1) + { + write(client->socket, "9: missing command\n", 19); + /* ignore failure */ } - + else if (strcmp(lines[0], "acl") == 0) { + info("acl command received" ); + if (control_acl(client, linesc-1, lines+1) < 0) { + debug("acl command failed"); + } + } + else if (strcmp(lines[0], "mirror") == 0) { + info("mirror command received" ); + if (control_mirror(client, linesc-1, lines+1) < 0) { + debug("mirror command failed"); + } + } + else if (strcmp(lines[0], "status") == 0) { + info("status command received" ); + if (control_status(client, linesc-1, lines+1) < 0) { + debug("status command failed"); + } + } + else { + write(client->socket, "10: unknown command\n", 23); + } + + for (i=0; icontrol ) { debug( "Stopping control thread" ); flexnbd_stop_control( flexnbd ); + debug("Control thread stopped"); } return success; diff --git a/tests/fakes/source/connect_from_banned_ip.rb b/tests/fakes/source/connect_from_banned_ip.rb new file mode 100755 index 0000000..98221fd --- /dev/null +++ b/tests/fakes/source/connect_from_banned_ip.rb @@ -0,0 +1,23 @@ +#!/usr/bin/env ruby +# encoding: utf-8 + +# We connect from a local address which should be blocked, sleep for a +# bit, then try to read from the socket. We should get an instant EOF +# as we've been cut off by the destination. + +require 'timeout' +require 'flexnbd/fake_source' +include FlexNBD::FakeSource + +addr, port = *ARGV +sock = connect( addr, port, "Timed out connecting", "127.0.0.6" ) +sleep( 0.25 ) +Timeout.timeout( 2 ) do + fail "Not disconnected" if sock.read(1) +end + +sock.close +exit(0) + + + diff --git a/tests/flexnbd.rb b/tests/flexnbd.rb index 229e2de..7109f83 100644 --- a/tests/flexnbd.rb +++ b/tests/flexnbd.rb @@ -265,6 +265,13 @@ class FlexNBD "#{@debug}" end + def acl_cmd( *acl ) + "#{@bin} acl " \ + "--sock #{ctrl} "\ + "#{@debug} "\ + "#{acl.join " "}" + end + def run_serve_cmd(cmd) File.unlink(ctrl) if File.exists?(ctrl) @@ -354,6 +361,7 @@ class FlexNBD @wait_thread.join end + def mirror_unchecked( dest_ip, dest_port, bandwidth=nil, action=nil, timeout=nil ) cmd = mirror_cmd( dest_ip, dest_port) debug( cmd ) @@ -361,6 +369,7 @@ class FlexNBD maybe_timeout( cmd, timeout ) end + def maybe_timeout(cmd, timeout=nil ) stdout, stderr = "","" run = Proc.new do @@ -388,8 +397,12 @@ class FlexNBD stdout end + def acl(*acl) - control_command("acl", *acl) + cmd = acl_cmd( *acl ) + debug( cmd ) + + maybe_timeout( cmd, 2 ) end @@ -403,6 +416,11 @@ class FlexNBD end + def launched? + !!@pid + end + + protected def control_command(*args) raise "Server not running" unless @pid diff --git a/tests/flexnbd/fake_source.rb b/tests/flexnbd/fake_source.rb index 40ae021..3a15c03 100644 --- a/tests/flexnbd/fake_source.rb +++ b/tests/flexnbd/fake_source.rb @@ -7,9 +7,9 @@ require 'flexnbd/constants' module FlexNBD module FakeSource - def connect( addr, port, err_msg ) + def connect( addr, port, err_msg, source_addr=nil, source_port=0 ) timing_out( 2, err_msg ) do - TCPSocket.open( addr, port ) + TCPSocket.new( addr, port, source_addr, source_port ) end end diff --git a/tests/nbd_scenarios b/tests/nbd_scenarios index 73fa21a..5a033fe 100644 --- a/tests/nbd_scenarios +++ b/tests/nbd_scenarios @@ -33,7 +33,7 @@ class Environment def listen1( *acl ) - @nbd1.listen( @filename1, *acl ) + @nbd1.listen( @filename1, *(acl.empty? ? @acl1: acl) ) end def listen2( *acl ) @@ -41,6 +41,15 @@ class Environment end + def acl1( *acl ) + @nbd1.acl( *acl ) + end + + def acl2( *acl ) + @nbd2.acl( *acl ) + end + + def status1 @nbd1.status.first end @@ -304,10 +313,16 @@ class NBDConnectDestFailureScenarios < Test::Unit::TestCase end + def test_acl_rejection + @env.acl1("127.0.0.1") + run_fake( "source/connect_from_banned_ip") + end + + private def run_fake( name ) @env.run_fake( name, @env.ip, @env.port1 ) - assert @env.fake_reports_success + assert @env.fake_reports_success, "#{name} failed." end def assert_no_control