mirror of
https://github.com/solemnwarning/ipxwrapper
synced 2024-12-30 16:45:37 +01:00
1088 lines
24 KiB
Perl
1088 lines
24 KiB
Perl
|
# IPXWrapper test suite
|
||
|
# Copyright (C) 2014 Daniel Collins <solemnwarning@solemnwarning.net>
|
||
|
#
|
||
|
# This program is free software; you can redistribute it and/or modify it
|
||
|
# under the terms of the GNU General Public License version 2 as published by
|
||
|
# the Free Software Foundation.
|
||
|
#
|
||
|
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
|
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||
|
# more details.
|
||
|
#
|
||
|
# You should have received a copy of the GNU General Public License along with
|
||
|
# this program; if not, write to the Free Software Foundation, Inc., 51
|
||
|
# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
|
||
|
use strict;
|
||
|
use warnings;
|
||
|
|
||
|
use Test::Spec;
|
||
|
|
||
|
use FindBin;
|
||
|
use lib "$FindBin::Bin/lib/";
|
||
|
|
||
|
use IPXWrapper::Capture::IPXOverUDP;
|
||
|
use IPXWrapper::Tool::IPXISR;
|
||
|
use IPXWrapper::Tool::IPXRecv;
|
||
|
use IPXWrapper::Util;
|
||
|
|
||
|
require "$FindBin::Bin/config.pm";
|
||
|
|
||
|
our ($local_dev_a, $local_mac_a, $local_ip_a);
|
||
|
our ($local_dev_b, $local_mac_b, $local_ip_b);
|
||
|
our ($remote_mac_a, $remote_ip_a);
|
||
|
our ($remote_mac_b, $remote_ip_b);
|
||
|
our ($net_a_bcast, $net_b_bcast);
|
||
|
|
||
|
require "$FindBin::Bin/ptype.pm";
|
||
|
|
||
|
our $ptype_send_func;
|
||
|
our $ptype_capture_class;
|
||
|
|
||
|
use constant {
|
||
|
UDP_BCAST_PORT => 54792,
|
||
|
};
|
||
|
|
||
|
my $node_c_net = "00:00:00:02";
|
||
|
|
||
|
describe "IPXWrapper using IP encapsulation" => sub
|
||
|
{
|
||
|
before all => sub
|
||
|
{
|
||
|
reg_delete_key($remote_ip_a, "HKCU\\Software\\IPXWrapper");
|
||
|
reg_set_addr( $remote_ip_a, "HKCU\\Software\\IPXWrapper\\00:00:00:00:00:00", "net", "00:00:00:01");
|
||
|
reg_set_addr( $remote_ip_a, "HKCU\\Software\\IPXWrapper\\$remote_mac_a", "net", "00:00:00:01");
|
||
|
reg_set_addr( $remote_ip_a, "HKCU\\Software\\IPXWrapper\\$remote_mac_b", "net", "00:00:00:02");
|
||
|
|
||
|
$node_c_net = "00:00:00:02";
|
||
|
};
|
||
|
|
||
|
describe "packets received on the shared port" => sub
|
||
|
{
|
||
|
they "are only accepted from the bound interface" => sub
|
||
|
{
|
||
|
my $capture_a = IPXWrapper::Tool::IPXRecv->new(
|
||
|
$remote_ip_a,
|
||
|
"-r", "00:00:00:00", $remote_mac_a, "4444",
|
||
|
);
|
||
|
|
||
|
my $capture_b = IPXWrapper::Tool::IPXRecv->new(
|
||
|
$remote_ip_a,
|
||
|
"-r", "00:00:00:00", $remote_mac_b, "4444",
|
||
|
);
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_a_bcast,
|
||
|
dest_port => UDP_BCAST_PORT,
|
||
|
src_ip => $local_ip_a,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => "00:00:00:01",
|
||
|
dest_node => $remote_mac_a,
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 1234,
|
||
|
|
||
|
data => "chamferer",
|
||
|
);
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_b_bcast,
|
||
|
dest_port => UDP_BCAST_PORT,
|
||
|
src_ip => $local_ip_b,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => "00:00:00:01",
|
||
|
dest_node => $remote_mac_a,
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 1234,
|
||
|
|
||
|
data => "fragmentariness",
|
||
|
);
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_a_bcast,
|
||
|
dest_port => UDP_BCAST_PORT,
|
||
|
src_ip => $local_ip_a,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => $node_c_net,
|
||
|
dest_node => $remote_mac_b,
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => $node_c_net,
|
||
|
src_node => $local_mac_b,
|
||
|
src_socket => 1234,
|
||
|
|
||
|
data => "dowy",
|
||
|
);
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_b_bcast,
|
||
|
dest_port => UDP_BCAST_PORT,
|
||
|
src_ip => $local_ip_b,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => $node_c_net,
|
||
|
dest_node => $remote_mac_b,
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => $node_c_net,
|
||
|
src_node => $local_mac_b,
|
||
|
src_socket => 1234,
|
||
|
|
||
|
data => "papermch",
|
||
|
);
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
my @packets_a = $capture_a->kill_and_read();
|
||
|
my @packets_b = $capture_b->kill_and_read();
|
||
|
|
||
|
cmp_hashes_partial(\@packets_a, [
|
||
|
{
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 1234,
|
||
|
|
||
|
data => "chamferer",
|
||
|
},
|
||
|
]);
|
||
|
|
||
|
cmp_hashes_partial(\@packets_b, [
|
||
|
{
|
||
|
src_network => $node_c_net,
|
||
|
src_node => $local_mac_b,
|
||
|
src_socket => 1234,
|
||
|
|
||
|
data => "papermch",
|
||
|
},
|
||
|
]);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
describe "packets received on the private port" => sub
|
||
|
{
|
||
|
they "are only accepted on the bound interface" => sub
|
||
|
{
|
||
|
my $isr_a = IPXWrapper::Tool::IPXISR->new($remote_ip_a,
|
||
|
"-r", "-b", "00:00:00:01", $remote_mac_a, "4444");
|
||
|
|
||
|
my $isr_b = IPXWrapper::Tool::IPXISR->new($remote_ip_a,
|
||
|
"-r", "-b", $node_c_net, $remote_mac_b, "4444");
|
||
|
|
||
|
my $port_a = determine_private_port($isr_a, $local_dev_a, "fleawort");
|
||
|
my $port_b = determine_private_port($isr_b, $local_dev_b, "effervesce");
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_a_bcast,
|
||
|
dest_port => $port_a,
|
||
|
src_ip => $local_ip_a,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => "00:00:00:01",
|
||
|
dest_node => $remote_mac_a,
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 5678,
|
||
|
|
||
|
data => "infernal",
|
||
|
);
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_b_bcast,
|
||
|
dest_port => $port_a,
|
||
|
src_ip => $local_ip_b,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => "00:00:00:01",
|
||
|
dest_node => $remote_mac_a,
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 5678,
|
||
|
|
||
|
data => "multireflex",
|
||
|
);
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_a_bcast,
|
||
|
dest_port => $port_b,
|
||
|
src_ip => $local_ip_a,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => $node_c_net,
|
||
|
dest_node => $remote_mac_b,
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => $node_c_net,
|
||
|
src_node => $local_mac_b,
|
||
|
src_socket => 5678,
|
||
|
|
||
|
data => "metropolises",
|
||
|
);
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_b_bcast,
|
||
|
dest_port => $port_b,
|
||
|
src_ip => $local_ip_b,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => $node_c_net,
|
||
|
dest_node => $remote_mac_b,
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => $node_c_net,
|
||
|
src_node => $local_mac_b,
|
||
|
src_socket => 5678,
|
||
|
|
||
|
data => "photoionization",
|
||
|
);
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
my @packets_a = $isr_a->kill_and_read();
|
||
|
my @packets_b = $isr_b->kill_and_read();
|
||
|
|
||
|
cmp_hashes_partial(\@packets_a, [
|
||
|
{
|
||
|
src_net => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 5678,
|
||
|
|
||
|
data => "infernal",
|
||
|
},
|
||
|
]);
|
||
|
|
||
|
cmp_hashes_partial(\@packets_b, [
|
||
|
{
|
||
|
src_net => $node_c_net,
|
||
|
src_node => $local_mac_b,
|
||
|
src_socket => 5678,
|
||
|
|
||
|
data => "photoionization",
|
||
|
},
|
||
|
]);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
describe "broadcast packets" => sub
|
||
|
{
|
||
|
they "are received by sockets with SO_BROADCAST" => sub
|
||
|
{
|
||
|
my $capture = IPXWrapper::Tool::IPXRecv->new(
|
||
|
$remote_ip_a,
|
||
|
"-b", "00:00:00:00", $remote_mac_a, "4444",
|
||
|
);
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_a_bcast,
|
||
|
dest_port => UDP_BCAST_PORT,
|
||
|
src_ip => $local_ip_a,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => "00:00:00:01",
|
||
|
dest_node => "FF:FF:FF:FF:FF:FF",
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "amity",
|
||
|
);
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
my @packets = $capture->kill_and_read();
|
||
|
|
||
|
cmp_hashes_partial(\@packets, [
|
||
|
{
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "amity",
|
||
|
},
|
||
|
]);
|
||
|
};
|
||
|
|
||
|
they "aren't received by sockets without SO_BROADCAST when win95 bug is enabled" => sub
|
||
|
{
|
||
|
reg_set_dword($remote_ip_a, "HKCU\\Software\\IPXWrapper", "w95_bug", 1);
|
||
|
|
||
|
my $capture = IPXWrapper::Tool::IPXRecv->new(
|
||
|
$remote_ip_a,
|
||
|
"00:00:00:00", $remote_mac_a, "4444",
|
||
|
);
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_a_bcast,
|
||
|
dest_port => UDP_BCAST_PORT,
|
||
|
src_ip => $local_ip_a,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => "00:00:00:01",
|
||
|
dest_node => "FF:FF:FF:FF:FF:FF",
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "unslotted",
|
||
|
);
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
my @packets = $capture->kill_and_read();
|
||
|
|
||
|
cmp_hashes_partial(\@packets, []);
|
||
|
};
|
||
|
|
||
|
they "are received by sockets without SO_BROADCAST when win95 bug is disabled" => sub
|
||
|
{
|
||
|
reg_set_dword($remote_ip_a, "HKCU\\Software\\IPXWrapper", "w95_bug", 0);
|
||
|
|
||
|
my $capture = IPXWrapper::Tool::IPXRecv->new(
|
||
|
$remote_ip_a,
|
||
|
"00:00:00:00", $remote_mac_a, "4444",
|
||
|
);
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_a_bcast,
|
||
|
dest_port => UDP_BCAST_PORT,
|
||
|
src_ip => $local_ip_a,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => "00:00:00:01",
|
||
|
dest_node => "FF:FF:FF:FF:FF:FF",
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "declivity",
|
||
|
);
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
my @packets = $capture->kill_and_read();
|
||
|
|
||
|
cmp_hashes_partial(\@packets, [
|
||
|
{
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "declivity",
|
||
|
},
|
||
|
]);
|
||
|
};
|
||
|
|
||
|
they "are received by concurrent sockets within the same process" => sub
|
||
|
{
|
||
|
my $capture = IPXWrapper::Tool::IPXRecv->new(
|
||
|
$remote_ip_a,
|
||
|
"-r", "-b", "00:00:00:00", $remote_mac_a, "4444",
|
||
|
"-r", "-b", "00:00:00:00", $remote_mac_a, "4444",
|
||
|
);
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_a_bcast,
|
||
|
dest_port => UDP_BCAST_PORT,
|
||
|
src_ip => $local_ip_a,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => "00:00:00:01",
|
||
|
dest_node => "FF:FF:FF:FF:FF:FF",
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "isohyet",
|
||
|
);
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
my @packets = $capture->kill_and_read();
|
||
|
|
||
|
cmp_hashes_partial(\@packets, [
|
||
|
{
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "isohyet",
|
||
|
},
|
||
|
|
||
|
{
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "isohyet",
|
||
|
},
|
||
|
]) and isnt($packets[0]->{sock}, $packets[1]->{sock});
|
||
|
};
|
||
|
|
||
|
they "are received by concurrent sockets in different processes" => sub
|
||
|
{
|
||
|
my $capture_a = IPXWrapper::Tool::IPXRecv->new(
|
||
|
$remote_ip_a,
|
||
|
"-r", "-b", "00:00:00:00", $remote_mac_a, "4444",
|
||
|
);
|
||
|
|
||
|
my $capture_b = IPXWrapper::Tool::IPXRecv->new(
|
||
|
$remote_ip_a,
|
||
|
"-r", "-b", "00:00:00:00", $remote_mac_a, "4444",
|
||
|
);
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_a_bcast,
|
||
|
dest_port => UDP_BCAST_PORT,
|
||
|
src_ip => $local_ip_a,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => "00:00:00:01",
|
||
|
dest_node => "FF:FF:FF:FF:FF:FF",
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "januaries",
|
||
|
);
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
my @packets_a = $capture_a->kill_and_read();
|
||
|
my @packets_b = $capture_b->kill_and_read();
|
||
|
|
||
|
cmp_hashes_partial(\@packets_a, [
|
||
|
{
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "januaries",
|
||
|
},
|
||
|
]);
|
||
|
|
||
|
cmp_hashes_partial(\@packets_b, [
|
||
|
{
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "januaries",
|
||
|
},
|
||
|
]);
|
||
|
};
|
||
|
|
||
|
# TODO
|
||
|
they "are only received on the bound interfaces";
|
||
|
};
|
||
|
|
||
|
describe "packets sent to an unknown address" => sub
|
||
|
{
|
||
|
they "are only broadcast on the bound interface" => sub
|
||
|
{
|
||
|
my $capture_a = IPXWrapper::Capture::IPXOverUDP->new($local_dev_a);
|
||
|
my $capture_b = IPXWrapper::Capture::IPXOverUDP->new($local_dev_b);
|
||
|
|
||
|
run_remote_cmd(
|
||
|
$remote_ip_a, "Z:\\tools\\ipx-send.exe",
|
||
|
"-d" => "ligule",
|
||
|
"-s" => "5555", "-h" => $remote_mac_a,
|
||
|
"00:00:00:01", "11:11:11:11:11:11", "4444",
|
||
|
);
|
||
|
|
||
|
run_remote_cmd(
|
||
|
$remote_ip_a, "Z:\\tools\\ipx-send.exe",
|
||
|
"-d" => "hardheads",
|
||
|
"-s" => "5555", "-h" => $remote_mac_b,
|
||
|
"00:00:00:02", "22:22:22:22:22:22", "4444",
|
||
|
);
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
my @packets_a = $capture_a->read_available();
|
||
|
my @packets_b = $capture_b->read_available();
|
||
|
|
||
|
cmp_hashes_partial(\@packets_a, [
|
||
|
{
|
||
|
src_ip => $remote_ip_a,
|
||
|
dst_ip => $net_a_bcast,
|
||
|
dst_port => UDP_BCAST_PORT,
|
||
|
|
||
|
dst_network => "00:00:00:01",
|
||
|
dst_node => "11:11:11:11:11:11",
|
||
|
dst_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $remote_mac_a,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "ligule",
|
||
|
},
|
||
|
]);
|
||
|
|
||
|
cmp_hashes_partial(\@packets_b, [
|
||
|
{
|
||
|
src_ip => $remote_ip_b,
|
||
|
dst_ip => $net_b_bcast,
|
||
|
dst_port => UDP_BCAST_PORT,
|
||
|
|
||
|
dst_network => "00:00:00:02",
|
||
|
dst_node => "22:22:22:22:22:22",
|
||
|
dst_socket => 4444,
|
||
|
|
||
|
src_network => $node_c_net,
|
||
|
src_node => $remote_mac_b,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "hardheads",
|
||
|
},
|
||
|
]);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
describe "packets sent to a known address" => sub
|
||
|
{
|
||
|
my @packets_a;
|
||
|
my @packets_b;
|
||
|
|
||
|
before all => sub
|
||
|
{
|
||
|
my $sender = IPXWrapper::Tool::IPXISR->new($remote_ip_a,
|
||
|
"00:00:00:01", $remote_mac_a, "7777");
|
||
|
|
||
|
# Send a packet from our target address. It
|
||
|
# isn't aimed at an open socket, but will still
|
||
|
# be seen by the router thread and should update
|
||
|
# the address cache.
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_a_bcast,
|
||
|
dest_port => UDP_BCAST_PORT,
|
||
|
src_ip => $local_ip_a,
|
||
|
src_port => 6666,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => "00:00:00:01",
|
||
|
dest_node => "FF:FF:FF:FF:FF:FF",
|
||
|
dest_socket => 7778,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 8888,
|
||
|
|
||
|
data => "",
|
||
|
);
|
||
|
|
||
|
# Lay in some chaff - send packets with other
|
||
|
# source addresses to make sure the correct
|
||
|
# address gets pulled out of the cache.
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_a_bcast,
|
||
|
dest_port => UDP_BCAST_PORT,
|
||
|
src_ip => $local_ip_a,
|
||
|
src_port => 6667,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => "00:00:00:01",
|
||
|
dest_node => "FF:FF:FF:FF:FF:FF",
|
||
|
dest_socket => 7778,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => "00:00:00:12:34:56",
|
||
|
src_socket => 8888,
|
||
|
|
||
|
data => "",
|
||
|
);
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_a_bcast,
|
||
|
dest_port => UDP_BCAST_PORT,
|
||
|
src_ip => $local_ip_a,
|
||
|
src_port => 6668,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => "00:00:00:01",
|
||
|
dest_node => "FF:FF:FF:FF:FF:FF",
|
||
|
dest_socket => 7778,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 8889,
|
||
|
|
||
|
data => "",
|
||
|
);
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
my $capture_a = IPXWrapper::Capture::IPXOverUDP->new($local_dev_a);
|
||
|
my $capture_b = IPXWrapper::Capture::IPXOverUDP->new($local_dev_b);
|
||
|
|
||
|
$sender->send("00:00:00:01", $local_mac_a, "8888", "nondomesticating");
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
@packets_a = $capture_a->read_available();
|
||
|
@packets_b = $capture_b->read_available();
|
||
|
};
|
||
|
|
||
|
they "are sent to the process's UDP port" => sub
|
||
|
{
|
||
|
cmp_hashes_partial(\@packets_a, [
|
||
|
{
|
||
|
src_ip => $remote_ip_a,
|
||
|
dst_ip => $local_ip_a,
|
||
|
dst_port => 6666,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $remote_mac_a,
|
||
|
src_socket => 7777,
|
||
|
|
||
|
dst_network => "00:00:00:01",
|
||
|
dst_node => $local_mac_a,
|
||
|
dst_socket => 8888,
|
||
|
|
||
|
data => "nondomesticating",
|
||
|
},
|
||
|
]);
|
||
|
};
|
||
|
|
||
|
they "aren't transmitted on the other network" => sub
|
||
|
{
|
||
|
cmp_hashes_partial(\@packets_b, []);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
describe "sockets bound to the wildcard interface" => sub
|
||
|
{
|
||
|
my ($wildcard_net, $wildcard_node);
|
||
|
|
||
|
before each => sub
|
||
|
{
|
||
|
return if(defined($wildcard_net));
|
||
|
|
||
|
my @interfaces = getsockopt_interfaces($remote_ip_a);
|
||
|
|
||
|
my ($wc) = grep {
|
||
|
$_->{node} ne $remote_mac_a && $_->{node} ne $remote_mac_b
|
||
|
} @interfaces;
|
||
|
|
||
|
die("Could not determine wildcard address")
|
||
|
unless($wc && (scalar @interfaces) == 3);
|
||
|
|
||
|
$wildcard_net = $wc->{net};
|
||
|
$wildcard_node = $wc->{node};
|
||
|
};
|
||
|
|
||
|
they "transmit broadcast packets on all underlying interfaces" => sub
|
||
|
{
|
||
|
my $capture_a = IPXWrapper::Capture::IPXOverUDP->new($local_dev_a);
|
||
|
my $capture_b = IPXWrapper::Capture::IPXOverUDP->new($local_dev_b);
|
||
|
|
||
|
run_remote_cmd(
|
||
|
$remote_ip_a, "Z:\\tools\\ipx-send.exe",
|
||
|
"-b",
|
||
|
"-h" => $wildcard_node,
|
||
|
"-s" => "5555",
|
||
|
"-d" => "tibetan",
|
||
|
"FF:FF:FF:FF", "FF:FF:FF:FF:FF:FF", "4444"
|
||
|
);
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
my @packets_a = $capture_a->read_available();
|
||
|
my @packets_b = $capture_b->read_available();
|
||
|
|
||
|
my $ref_packet = sub
|
||
|
{
|
||
|
my ($dst_ip) = @_;
|
||
|
|
||
|
return {
|
||
|
dst_port => UDP_BCAST_PORT,
|
||
|
dst_ip => $dst_ip,
|
||
|
|
||
|
dst_network => "FF:FF:FF:FF",
|
||
|
dst_node => "FF:FF:FF:FF:FF:FF",
|
||
|
dst_socket => 4444,
|
||
|
|
||
|
src_network => $wildcard_net,
|
||
|
src_node => $wildcard_node,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "tibetan",
|
||
|
};
|
||
|
};
|
||
|
|
||
|
cmp_hashes_partial(\@packets_a, [ $ref_packet->($net_a_bcast) ]);
|
||
|
cmp_hashes_partial(\@packets_b, [ $ref_packet->($net_b_bcast) ]);
|
||
|
};
|
||
|
|
||
|
they "receive broadcast packets on all underlying interfaces" => sub
|
||
|
{
|
||
|
my $capture = IPXWrapper::Tool::IPXRecv->new(
|
||
|
$remote_ip_a,
|
||
|
"-b", "00:00:00:00", $wildcard_node, "4444",
|
||
|
);
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_a_bcast,
|
||
|
dest_port => UDP_BCAST_PORT,
|
||
|
src_ip => $local_ip_a,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => "00:00:00:01",
|
||
|
dest_node => "FF:FF:FF:FF:FF:FF",
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "overtake",
|
||
|
);
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_b_bcast,
|
||
|
dest_port => UDP_BCAST_PORT,
|
||
|
src_ip => $local_ip_b,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => "00:00:00:01",
|
||
|
dest_node => "FF:FF:FF:FF:FF:FF",
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_b,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "leakey",
|
||
|
);
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
my @packets = $capture->kill_and_read();
|
||
|
|
||
|
cmp_hashes_partial(\@packets, [
|
||
|
{
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "overtake",
|
||
|
},
|
||
|
|
||
|
{
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_b,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "leakey",
|
||
|
},
|
||
|
]);
|
||
|
};
|
||
|
|
||
|
they "broadcast packets to an unknown address on all underlying interfaces" => sub
|
||
|
{
|
||
|
my $capture_a = IPXWrapper::Capture::IPXOverUDP->new($local_dev_a);
|
||
|
my $capture_b = IPXWrapper::Capture::IPXOverUDP->new($local_dev_b);
|
||
|
|
||
|
run_remote_cmd(
|
||
|
$remote_ip_a, "Z:\\tools\\ipx-send.exe",
|
||
|
"-h", $wildcard_node, "-s", "5555",
|
||
|
"-d", "bowdrill",
|
||
|
"00:00:00:01", "11:11:11:11:11:11", "4444",
|
||
|
);
|
||
|
|
||
|
run_remote_cmd(
|
||
|
$remote_ip_a, "Z:\\tools\\ipx-send.exe",
|
||
|
"-h", $wildcard_node, "-s", "5555",
|
||
|
"-d", "developer",
|
||
|
"00:00:00:02", "22:22:22:22:22:22", "4444",
|
||
|
);
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
my @packets_a = $capture_a->read_available();
|
||
|
my @packets_b = $capture_b->read_available();
|
||
|
|
||
|
cmp_hashes_partial(\@packets_a, [
|
||
|
{
|
||
|
src_ip => $remote_ip_a,
|
||
|
dst_ip => $net_a_bcast,
|
||
|
dst_port => UDP_BCAST_PORT,
|
||
|
|
||
|
dst_network => "00:00:00:01",
|
||
|
dst_node => "11:11:11:11:11:11",
|
||
|
dst_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $wildcard_node,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "bowdrill",
|
||
|
},
|
||
|
|
||
|
{
|
||
|
src_ip => $remote_ip_a,
|
||
|
dst_ip => $net_a_bcast,
|
||
|
dst_port => UDP_BCAST_PORT,
|
||
|
|
||
|
dst_network => "00:00:00:02",
|
||
|
dst_node => "22:22:22:22:22:22",
|
||
|
dst_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $wildcard_node,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "developer",
|
||
|
},
|
||
|
]);
|
||
|
|
||
|
cmp_hashes_partial(\@packets_b, [
|
||
|
{
|
||
|
src_ip => $remote_ip_b,
|
||
|
dst_ip => $net_b_bcast,
|
||
|
dst_port => UDP_BCAST_PORT,
|
||
|
|
||
|
dst_network => "00:00:00:01",
|
||
|
dst_node => "11:11:11:11:11:11",
|
||
|
dst_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $wildcard_node,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "bowdrill",
|
||
|
},
|
||
|
|
||
|
{
|
||
|
src_ip => $remote_ip_b,
|
||
|
dst_ip => $net_b_bcast,
|
||
|
dst_port => UDP_BCAST_PORT,
|
||
|
|
||
|
dst_network => "00:00:00:02",
|
||
|
dst_node => "22:22:22:22:22:22",
|
||
|
dst_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $wildcard_node,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "developer",
|
||
|
},
|
||
|
]);
|
||
|
};
|
||
|
|
||
|
# TODO: Test transmission to a known IPX address.
|
||
|
|
||
|
they "receive unicast packets on all underlying interfaces" => sub
|
||
|
{
|
||
|
# TODO: Sent to private port, or not bcast at least.
|
||
|
|
||
|
my $capture = IPXWrapper::Tool::IPXRecv->new(
|
||
|
$remote_ip_a,
|
||
|
"00:00:00:00", $wildcard_node, "4444",
|
||
|
);
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_a_bcast,
|
||
|
dest_port => UDP_BCAST_PORT,
|
||
|
src_ip => $local_ip_a,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => "00:00:00:01",
|
||
|
dest_node => $wildcard_node,
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "orville",
|
||
|
);
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_b_bcast,
|
||
|
dest_port => UDP_BCAST_PORT,
|
||
|
src_ip => $local_ip_b,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => "00:00:00:01",
|
||
|
dest_node => $wildcard_node,
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_b,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "eliminability",
|
||
|
);
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
my @packets = $capture->kill_and_read();
|
||
|
|
||
|
cmp_hashes_partial(\@packets, [
|
||
|
{
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "orville",
|
||
|
},
|
||
|
|
||
|
{
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_b,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "eliminability",
|
||
|
},
|
||
|
]);
|
||
|
};
|
||
|
|
||
|
they "do not receive packets addressed to underlying interfaces" => sub
|
||
|
{
|
||
|
my $capture = IPXWrapper::Tool::IPXRecv->new(
|
||
|
$remote_ip_a,
|
||
|
"00:00:00:00", $wildcard_node, "4444",
|
||
|
);
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_a_bcast,
|
||
|
dest_port => UDP_BCAST_PORT,
|
||
|
src_ip => $local_ip_a,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => "00:00:00:01",
|
||
|
dest_node => $remote_mac_a,
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "antisuffragist",
|
||
|
);
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_b_bcast,
|
||
|
dest_port => UDP_BCAST_PORT,
|
||
|
src_ip => $local_ip_b,
|
||
|
|
||
|
type => 0,
|
||
|
|
||
|
dest_network => "00:00:00:02",
|
||
|
dest_node => $remote_mac_b,
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_b,
|
||
|
src_socket => 5555,
|
||
|
|
||
|
data => "ambrosiaceous",
|
||
|
);
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
my @packets = $capture->kill_and_read();
|
||
|
|
||
|
cmp_hashes_partial(\@packets, []);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
before all => sub
|
||
|
{
|
||
|
$ptype_capture_class = "IPXWrapper::Capture::IPXOverUDP";
|
||
|
|
||
|
$ptype_send_func = sub
|
||
|
{
|
||
|
my ($type, $data) = @_;
|
||
|
|
||
|
send_ipx_over_udp(
|
||
|
dest_ip => $net_a_bcast,
|
||
|
dest_port => UDP_BCAST_PORT,
|
||
|
src_ip => $local_ip_a,
|
||
|
|
||
|
type => $type,
|
||
|
|
||
|
dest_network => "00:00:00:01",
|
||
|
dest_node => $remote_mac_a,
|
||
|
dest_socket => 4444,
|
||
|
|
||
|
src_network => "00:00:00:01",
|
||
|
src_node => $local_mac_a,
|
||
|
src_socket => 1234,
|
||
|
|
||
|
data => $data,
|
||
|
);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
it_should_behave_like "ipx packet type handling";
|
||
|
};
|
||
|
|
||
|
runtests unless caller;
|
||
|
|
||
|
sub determine_private_port
|
||
|
{
|
||
|
my ($isr, $capture_dev, $key) = @_;
|
||
|
|
||
|
my $capture = IPXWrapper::Capture::IPXOverUDP->new($capture_dev);
|
||
|
|
||
|
$isr->send("00:00:00:00", "FF:FF:FF:FF:FF:FF", "1234", $key);
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
my ($ip_packet) = grep { $_->{data} eq $key }
|
||
|
$capture->read_available();
|
||
|
|
||
|
die("Couldn't determine port number of process")
|
||
|
unless($ip_packet);
|
||
|
|
||
|
return $ip_packet->{src_port};
|
||
|
}
|