1
0
mirror of https://github.com/solemnwarning/ipxwrapper synced 2024-12-30 16:45:37 +01:00

Allow sending Novell/LLC frames up to the maximum size.

This commit is contained in:
Daniel Collins 2017-08-20 22:59:49 +01:00
parent b58ef3eb1e
commit ba7fa5a77f
9 changed files with 132 additions and 25 deletions

View File

@ -154,17 +154,15 @@ bool ethII_frame_unpack(const novell_ipx_packet **packet, size_t *packet_len, co
size_t novell_frame_size(size_t ipx_payload_len) size_t novell_frame_size(size_t ipx_payload_len)
{ {
static const size_t OVERHEAD
= sizeof(ethernet_header)
+ sizeof(novell_ipx_packet);
if(ipx_payload_len > NOVELL_IPX_PACKET_MAX_PAYLOAD if(ipx_payload_len > NOVELL_IPX_PACKET_MAX_PAYLOAD
|| ipx_payload_len > (1500 - OVERHEAD)) || ipx_payload_len > (1500 - sizeof(novell_ipx_packet)))
{ {
return 0; return 0;
} }
return OVERHEAD + ipx_payload_len; return sizeof(ethernet_header)
+ sizeof(novell_ipx_packet)
+ ipx_payload_len;
} }
void novell_frame_pack(void *frame_buffer, void novell_frame_pack(void *frame_buffer,
@ -224,18 +222,16 @@ bool novell_frame_unpack(const novell_ipx_packet **packet, size_t *packet_len, c
size_t llc_frame_size(size_t ipx_payload_len) size_t llc_frame_size(size_t ipx_payload_len)
{ {
static const size_t OVERHEAD
= sizeof(ethernet_header)
+ sizeof(llc_header)
+ sizeof(novell_ipx_packet);
if(ipx_payload_len > NOVELL_IPX_PACKET_MAX_PAYLOAD if(ipx_payload_len > NOVELL_IPX_PACKET_MAX_PAYLOAD
|| ipx_payload_len > (1500 - OVERHEAD)) || ipx_payload_len > (1500 - (sizeof(llc_header) + sizeof(novell_ipx_packet))))
{ {
return 0; return 0;
} }
return OVERHEAD + ipx_payload_len; return sizeof(ethernet_header)
+ sizeof(llc_header)
+ sizeof(novell_ipx_packet)
+ ipx_payload_len;
} }
void llc_frame_pack(void *frame_buffer, void llc_frame_pack(void *frame_buffer,

View File

@ -44,6 +44,7 @@ my $node_c_net = "00:00:00:00";
my $ipx_eth_capture_class; my $ipx_eth_capture_class;
my $ipx_eth_send_func; my $ipx_eth_send_func;
my $max_payload_size;
shared_examples_for "ipx over ethernet" => sub shared_examples_for "ipx over ethernet" => sub
{ {
@ -502,6 +503,96 @@ shared_examples_for "ipx over ethernet" => sub
}; };
}; };
it "can transmit the largest possible packet" => sub
{
my $capture = $ipx_eth_capture_class->new($local_dev_a);
run_remote_cmd(
$remote_ip_a, "Z:\\tools\\ipx-send.exe",
"-l" => $max_payload_size,
"-s" => "4324", "-h" => $remote_mac_a,
"00:00:00:01", $local_mac_a, "6789",
);
sleep(1);
my @packets = $capture->read_available();
cmp_hashes_partial(\@packets, [
{
src_network => "00:00:00:01",
src_node => $remote_mac_a,
src_socket => 4324,
dst_network => "00:00:00:01",
dst_node => $local_mac_a,
dst_socket => 6789,
data => (chr(0xAA) x $max_payload_size),
},
]);
};
it "refuses to transmit larger than the largest possible packet" => sub
{
my $capture = $ipx_eth_capture_class->new($local_dev_a);
trap {
run_remote_cmd(
$remote_ip_a, "Z:\\tools\\ipx-send.exe",
"-l" => $max_payload_size + 1,
"-s" => "1111", "-h" => $remote_mac_a,
"00:00:00:01", $local_mac_a, "2222",
);
};
sleep(1);
# Ensure sendto() failed with WSAEMSGSIZE
like($trap->die(), qr/^sendto: 10040$/m);
# Ensure no packets were transmitted.
my @packets = $capture->read_available();
cmp_hashes_partial(\@packets, []);
};
it "can receive the largest possible packet" => sub
{
my $capture = IPXWrapper::Tool::IPXRecv->new(
$remote_ip_a,
"00:00:00:00", $remote_mac_a, "3456",
);
$ipx_eth_send_func->($local_dev_a,
tc => 0,
type => 0,
dest_network => "00:00:00:01",
dest_node => $remote_mac_a,
dest_socket => 3456,
src_network => "00:00:00:01",
src_node => $local_mac_a,
src_socket => 4567,
data => ("x" x $max_payload_size),
);
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 => 4567,
data => ("x" x $max_payload_size),
},
]);
};
before all => sub before all => sub
{ {
$ptype_capture_class = $ipx_eth_capture_class; $ptype_capture_class = $ipx_eth_capture_class;
@ -542,6 +633,7 @@ describe "IPXWrapper using Ethernet encapsulation" => sub
$ipx_eth_capture_class = "IPXWrapper::Capture::IPX"; $ipx_eth_capture_class = "IPXWrapper::Capture::IPX";
$ipx_eth_send_func = \&send_ipx_packet_ethernet; $ipx_eth_send_func = \&send_ipx_packet_ethernet;
$max_payload_size = 1470;
}; };
it_should_behave_like "ipx over ethernet"; it_should_behave_like "ipx over ethernet";
@ -559,6 +651,7 @@ describe "IPXWrapper using Novell Ethernet encapsulation" => sub
$ipx_eth_capture_class = "IPXWrapper::Capture::IPXNovell"; $ipx_eth_capture_class = "IPXWrapper::Capture::IPXNovell";
$ipx_eth_send_func = \&send_ipx_packet_novell; $ipx_eth_send_func = \&send_ipx_packet_novell;
$max_payload_size = 1470;
}; };
it_should_behave_like "ipx over ethernet"; it_should_behave_like "ipx over ethernet";
@ -576,6 +669,7 @@ describe "IPXWrapper using LLC (802.2) Ethernet encapsulation" => sub
$ipx_eth_capture_class = "IPXWrapper::Capture::IPXLLC"; $ipx_eth_capture_class = "IPXWrapper::Capture::IPXLLC";
$ipx_eth_send_func = \&send_ipx_packet_llc; $ipx_eth_send_func = \&send_ipx_packet_llc;
$max_payload_size = 1467;
}; };
it_should_behave_like "ipx over ethernet"; it_should_behave_like "ipx over ethernet";

View File

@ -241,8 +241,8 @@ int main()
CHECK_FRAME_SIZE(novell_frame_size, 0, 44); CHECK_FRAME_SIZE(novell_frame_size, 0, 44);
CHECK_FRAME_SIZE(novell_frame_size, 50, 94); CHECK_FRAME_SIZE(novell_frame_size, 50, 94);
CHECK_FRAME_SIZE(novell_frame_size, 1456, 1500); CHECK_FRAME_SIZE(novell_frame_size, 1470, 1514);
CHECK_FRAME_SIZE(novell_frame_size, 1457, 0); CHECK_FRAME_SIZE(novell_frame_size, 1471, 0);
/* +===================+ /* +===================+
* | novell_frame_pack | * | novell_frame_pack |
@ -510,8 +510,8 @@ int main()
CHECK_FRAME_SIZE(llc_frame_size, 0, 47); CHECK_FRAME_SIZE(llc_frame_size, 0, 47);
CHECK_FRAME_SIZE(llc_frame_size, 50, 97); CHECK_FRAME_SIZE(llc_frame_size, 50, 97);
CHECK_FRAME_SIZE(llc_frame_size, 1453, 1500); CHECK_FRAME_SIZE(llc_frame_size, 1467, 1514);
CHECK_FRAME_SIZE(llc_frame_size, 1454, 0); CHECK_FRAME_SIZE(llc_frame_size, 1468, 0);
/* +================+ /* +================+
* | llc_frame_pack | * | llc_frame_pack |

View File

@ -28,7 +28,7 @@ sub new
my ($class, $dev) = @_; my ($class, $dev) = @_;
my $err; my $err;
my $pcap = Net::Pcap::pcap_open_live($dev, 1500, 0, 1, \$err) my $pcap = Net::Pcap::pcap_open_live($dev, 2000, 0, 1, \$err)
or die("Cannot open device $dev: $err"); or die("Cannot open device $dev: $err");
return bless(\$pcap, $class); return bless(\$pcap, $class);

View File

@ -28,7 +28,7 @@ sub new
my ($class, $dev) = @_; my ($class, $dev) = @_;
my $err; my $err;
my $pcap = Net::Pcap::pcap_open_live($dev, 1500, 0, 1, \$err) my $pcap = Net::Pcap::pcap_open_live($dev, 2000, 0, 1, \$err)
or die("Cannot open device $dev: $err"); or die("Cannot open device $dev: $err");
return bless(\$pcap, $class); return bless(\$pcap, $class);

View File

@ -28,7 +28,7 @@ sub new
my ($class, $dev) = @_; my ($class, $dev) = @_;
my $err; my $err;
my $pcap = Net::Pcap::pcap_open_live($dev, 1500, 0, 1, \$err) my $pcap = Net::Pcap::pcap_open_live($dev, 2000, 0, 1, \$err)
or die("Cannot open device $dev: $err"); or die("Cannot open device $dev: $err");
return bless(\$pcap, $class); return bless(\$pcap, $class);

View File

@ -55,12 +55,14 @@ sub run_remote_cmd
note(join(" ", @command)); note(join(" ", @command));
my $output = ""; my $output = "";
IPC::Run::run(\@command, ">&" => \$output) my $ok = IPC::Run::run(\@command, ">&" => \$output);
or die("Failure running $exe_name:\n$output");
# Oh line endings, how do I hate thee? Let me count the ways. # Oh line endings, how do I hate thee? Let me count the ways.
$output =~ s/\r//g; $output =~ s/\r//g;
die("Failure running $exe_name:\n$output")
unless($ok);
return $output; return $output;
} }

View File

@ -28,7 +28,7 @@
#include "tools.h" #include "tools.h"
const int MAX_SOCKETS = 32; const int MAX_SOCKETS = 32;
const int BUFSIZE = 64; const int BUFSIZE = 2048;
static void usage(const char *argv0) static void usage(const char *argv0)
{ {

View File

@ -43,7 +43,7 @@ int main(int argc, char **argv)
BOOL reuse = FALSE; BOOL reuse = FALSE;
int opt; int opt;
while((opt = getopt(argc, argv, "n:h:s:t:d:br")) != -1) while((opt = getopt(argc, argv, "n:h:s:t:d:l:br")) != -1)
{ {
if(opt == 'n') if(opt == 'n')
{ {
@ -65,6 +65,13 @@ int main(int argc, char **argv)
{ {
data = optarg; data = optarg;
} }
else if(opt == 'l')
{
int len = atoi(optarg);
assert((data = malloc(len)) != NULL);
memset((char*)(data), 0xAA, len);
}
else if(opt == 'b') else if(opt == 'b')
{ {
bcast = TRUE; bcast = TRUE;
@ -87,6 +94,7 @@ int main(int argc, char **argv)
"[-s <local socket number>]\n" "[-s <local socket number>]\n"
"[-t <packet type>]\n" "[-t <packet type>]\n"
"[-d <payload>]\n" "[-d <payload>]\n"
"[-l <payload length>]\n"
"[-b (enable SO_BROADCAST)]\n" "[-b (enable SO_BROADCAST)]\n"
"[-r (enable SO_REUSEADDR)]\n" "[-r (enable SO_REUSEADDR)]\n"
"<remote network number>\n" "<remote network number>\n"
@ -132,7 +140,14 @@ int main(int argc, char **argv)
printf("Bound to local address: %s\n", formatted_addr); printf("Bound to local address: %s\n", formatted_addr);
} }
assert(sendto(sock, data, strlen(data), 0, (struct sockaddr*)(&remote_addr), sizeof(remote_addr)) == strlen(data)); int sr = sendto(sock, data, strlen(data), 0, (struct sockaddr*)(&remote_addr), sizeof(remote_addr));
if(sr == -1)
{
fprintf(stderr, "sendto: %u\n", (unsigned int)(WSAGetLastError()));
return 1;
}
assert(sr == strlen(data));
closesocket(sock); closesocket(sock);