1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-23 02:35:57 +01:00

Add active test for TCP over ethernet

This commit is contained in:
Matias Fontanini
2016-03-26 16:11:03 -07:00
parent 6aac22fa74
commit d80c27de29
9 changed files with 198 additions and 39 deletions

View File

@@ -66,8 +66,10 @@ public:
void validate(PacketCapturer::PacketStorage& packets);
virtual std::string name() const = 0;
protected:
const PacketSenderPtr& packet_sender() const;
const ConfigurationPtr& configuration() const;
Tins::PacketSender& packet_sender();
const Tins::PacketSender& packet_sender() const;
Configuration& configuration();
const Configuration& configuration() const;
virtual bool test_matches_packet(const Tins::PDU& pdu) const = 0;
virtual void execute_test() = 0;
virtual void validate_packet(const Tins::PDU& pdu) = 0;

View File

@@ -37,16 +37,40 @@
class TCPSynTest : public ActiveTest {
public:
TCPSynTest(const PacketSenderPtr& packet_sender,
const ConfigurationPtr& configuration);
std::string name() const;
const ConfigurationPtr& configuration,
uint16_t target_port);
private:
void execute_test();
void validate_packet(const Tins::PDU& pdu);
bool test_matches_packet(const Tins::PDU& pdu) const;
virtual void send_packet(Tins::PDU& pdu) = 0;
Tins::IPv4Address target_address_;
uint32_t sequence_number_;
uint16_t target_port_;
};
// Sends a SYN using IP as the lowest layer
class Layer3TCPSynTest : public TCPSynTest {
public:
Layer3TCPSynTest(const PacketSenderPtr& packet_sender,
const ConfigurationPtr& configuration);
std::string name() const;
private:
void send_packet(Tins::PDU& pdu);
};
// Sends a SYN using Ethernet as the lowest layer
class Layer2TCPSynTest : public TCPSynTest {
public:
Layer2TCPSynTest(const PacketSenderPtr& packet_sender,
const ConfigurationPtr& configuration);
std::string name() const;
private:
void send_packet(Tins::PDU& pdu);
};
#endif // TINS_ACTIVE_TCP_TESTS_H

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_TEST_UTILS_H
#define TINS_TEST_UTILS_H
#include <string>
#include "tins/ip_address.h"
Tins::IPv4Address get_gateway_v4_address(const std::string& interface_name);
#endif // TINS_TEST_UTILS_H

View File

@@ -37,6 +37,7 @@ using std::endl;
using std::string;
using Tins::PDU;
using Tins::PacketSender;
using Tins::pdu_not_found;
using Tins::option_not_found;
@@ -96,12 +97,20 @@ void ActiveTest::validate(PacketCapturer::PacketStorage& packets) {
}
}
const ActiveTest::PacketSenderPtr& ActiveTest::packet_sender() const {
return packet_sender_;
PacketSender& ActiveTest::packet_sender() {
return *packet_sender_;
}
const ActiveTest::ConfigurationPtr& ActiveTest::configuration() const {
return configuration_;
const PacketSender& ActiveTest::packet_sender() const {
return *packet_sender_;
}
Configuration& ActiveTest::configuration() {
return *configuration_;
}
const Configuration& ActiveTest::configuration() const {
return *configuration_;
}
void ActiveTest::disable_on_platform(Configuration::Platform platform) {

View File

@@ -59,8 +59,8 @@ string IPv4SourceAddressTest::name() const {
}
void IPv4SourceAddressTest::execute_test() {
PacketSender& sender = *packet_sender();
Configuration& config = *configuration();
PacketSender& sender = packet_sender();
Configuration& config = configuration();
auto packet = IP("8.8.8.8");
packet /= UDP(config.destination_port(), config.source_port());
packet /= RawPDU(name());
@@ -69,7 +69,7 @@ void IPv4SourceAddressTest::execute_test() {
void IPv4SourceAddressTest::validate_packet(const PDU& pdu) {
const IP& ip = pdu.rfind_pdu<IP>();
const NetworkInterface& iface = configuration()->interface();
const NetworkInterface& iface = configuration().interface();
// The source address should be the same as the default interface's
if (iface.ipv4_address() != ip.src_addr()) {
ostringstream oss;
@@ -98,8 +98,8 @@ string IPv4FragmentationTest::name() const {
}
void IPv4FragmentationTest::execute_test() {
PacketSender& sender = *packet_sender();
Configuration& config = *configuration();
PacketSender& sender = packet_sender();
Configuration& config = configuration();
auto packet = IP("8.8.8.8");
packet /= UDP(config.destination_port(), config.source_port());
packet /= RawPDU(name());

View File

@@ -53,7 +53,8 @@ int main() {
ActiveTestRunner runner(config);
runner.add_test<IPv4SourceAddressTest>();
runner.add_test<IPv4FragmentationTest>();
runner.add_test<TCPSynTest>();
runner.add_test<Layer3TCPSynTest>();
runner.add_test<Layer2TCPSynTest>();
runner.add_test<ResolveHWAddressTest>();
if (!runner.validate_tests()) {

View File

@@ -32,7 +32,9 @@
#include "tcp_tests.h"
#include "tins/tcp.h"
#include "tins/ip.h"
#include "tins/ethernetII.h"
#include "tins/utils.h"
#include "test_utils.h"
using std::string;
using std::cout;
@@ -42,16 +44,16 @@ using std::random_device;
using Tins::PDU;
using Tins::TCP;
using Tins::IP;
using Tins::IPv4Address;
using Tins::NetworkInterface;
using Tins::EthernetII;
using Tins::Utils::resolve_domain;
TCPSynTest::TCPSynTest(const PacketSenderPtr& packet_sender,
const ConfigurationPtr& configuration)
: ActiveTest(packet_sender, configuration) {
disable_on_platform(Configuration::WINDOWS);
}
const ConfigurationPtr& configuration,
uint16_t target_port)
: ActiveTest(packet_sender, configuration), target_port_(target_port) {
string TCPSynTest::name() const {
return "tcp_syn_test";
}
void TCPSynTest::execute_test() {
@@ -60,11 +62,11 @@ void TCPSynTest::execute_test() {
sequence_number_ = static_cast<uint32_t>(rnd());
cout << log_prefix() << "Resolved target address to " << target_address_ << endl;
auto packet = IP(target_address_) / TCP(80, configuration()->source_port());
auto packet = IP(target_address_) / TCP(target_port_, configuration().source_port());
TCP& tcp = packet.rfind_pdu<TCP>();
tcp.seq(sequence_number_);
tcp.flags(TCP::SYN);
packet_sender()->send(packet);
send_packet(packet);
}
void TCPSynTest::validate_packet(const PDU& pdu) {
@@ -79,9 +81,48 @@ bool TCPSynTest::test_matches_packet(const PDU& pdu) const {
return false;
}
const TCP& tcp = pdu.rfind_pdu<TCP>();
if (tcp.sport() != 80) {
if (tcp.sport() != target_port_) {
return false;
}
return tcp.ack_seq() == sequence_number_ + 1;
}
// Layer 3
Layer3TCPSynTest::Layer3TCPSynTest(const PacketSenderPtr& packet_sender,
const ConfigurationPtr& configuration)
: TCPSynTest(packet_sender, configuration, 80) {
disable_on_platform(Configuration::WINDOWS);
}
string Layer3TCPSynTest::name() const {
return "tcp_layer3_syn_test";
}
void Layer3TCPSynTest::send_packet(PDU& pdu) {
packet_sender().send(pdu);
}
// Layer 2
Layer2TCPSynTest::Layer2TCPSynTest(const PacketSenderPtr& packet_sender,
const ConfigurationPtr& configuration)
: TCPSynTest(packet_sender, configuration, 443) {
}
string Layer2TCPSynTest::name() const {
return "tcp_layer2_syn_test";
}
void Layer2TCPSynTest::send_packet(PDU& pdu) {
const NetworkInterface& iface = configuration().interface();
IPv4Address gateway_address = get_gateway_v4_address(iface.name());
auto gateway_hwaddress = Tins::Utils::resolve_hwaddr(iface, gateway_address,
packet_sender());
EthernetII eth = EthernetII(gateway_hwaddress, iface.hw_address()) / pdu;
eth.rfind_pdu<IP>().src_addr(iface.ipv4_address());
packet_sender().send(eth);
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <limits>
#include "test_utils.h"
#include "tins/utils.h"
using std::string;
using std::vector;
using std::numeric_limits;
using Tins::IPv4Address;
using Tins::Utils::RouteEntry;
IPv4Address get_gateway_v4_address(const string& interface_name) {
vector<RouteEntry> entries = Tins::Utils::route_entries();
int current_metric = numeric_limits<int>::max();
IPv4Address address;
for (const auto& entry : entries) {
if (entry.interface == interface_name && entry.gateway != "0.0.0.0" && entry.metric < current_metric) {
address = entry.gateway;
current_metric = entry.metric;
}
}
return address;
}

View File

@@ -34,6 +34,7 @@
#include "tins/ethernetII.h"
#include "tins/arp.h"
#include "tins/utils.h"
#include "test_utils.h"
using std::cout;
using std::endl;
@@ -52,16 +53,7 @@ using Tins::Utils::RouteEntry;
ResolveHWAddressTest::ResolveHWAddressTest(const PacketSenderPtr& packet_sender,
const ConfigurationPtr& configuration)
: ActiveTest(packet_sender, configuration) {
vector<RouteEntry> entries = Tins::Utils::route_entries();
string interface_name = configuration->interface().name();
int current_metric = numeric_limits<int>::max();
for (const auto& entry : entries) {
if (entry.interface == interface_name && entry.gateway != "0.0.0.0" && entry.metric < current_metric) {
target_address_ = entry.gateway;
current_metric = entry.metric;
}
}
disable_on_platform(Configuration::WINDOWS);
target_address_ = get_gateway_v4_address(configuration->interface().name());
}
string ResolveHWAddressTest::name() const {
@@ -75,14 +67,14 @@ bool ResolveHWAddressTest::test_matches_packet(const PDU& pdu) const {
void ResolveHWAddressTest::execute_test() {
cout << log_prefix() << "trying to resolve " << target_address_ << endl;
resolved_address_ = Tins::Utils::resolve_hwaddr(configuration()->interface(),
resolved_address_ = Tins::Utils::resolve_hwaddr(configuration().interface(),
target_address_,
*packet_sender());
packet_sender());
cout << log_prefix() << "address resolved to " << resolved_address_ << endl;
auto local_ip_address = configuration()->interface().ipv4_address();
auto local_hw_address = configuration()->interface().hw_address();
auto local_ip_address = configuration().interface().ipv4_address();
auto local_hw_address = configuration().interface().hw_address();
auto packet = ARP::make_arp_request(target_address_, local_ip_address, local_hw_address);
packet_sender()->send(packet);
packet_sender().send(packet);
}
void ResolveHWAddressTest::validate_packet(const PDU& pdu) {