mirror of
https://github.com/openappsec/openappsec.git
synced 2025-09-29 19:24:26 +03:00
First release of open-appsec source code
This commit is contained in:
2
components/packet/CMakeLists.txt
Normal file
2
components/packet/CMakeLists.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
add_library(packet packet.cc)
|
||||
add_subdirectory(packet_ut)
|
607
components/packet/packet.cc
Executable file
607
components/packet/packet.cc
Executable file
@@ -0,0 +1,607 @@
|
||||
#include "packet.h"
|
||||
#include "debug.h"
|
||||
#include "byteorder.h"
|
||||
#include "c_common/network_defs.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
USE_DEBUG_FLAG(D_PACKET);
|
||||
|
||||
ostream &
|
||||
operator<<(ostream &os, const PktErr &err)
|
||||
{
|
||||
switch (err) {
|
||||
case PktErr::UNINITIALIZED: {
|
||||
return os << "Uninitialized packet";
|
||||
}
|
||||
case PktErr::NON_ETHERNET_FRAME: {
|
||||
return os << "Layer 2 frame length does not match the Ethernet frame length";
|
||||
}
|
||||
case PktErr::MAC_LEN_TOO_BIG: {
|
||||
return os << "Layer 2 frame length is greater than the packet length";
|
||||
}
|
||||
case PktErr::NON_IP_PACKET: {
|
||||
return os << "Ethernet frame contains a non-IP packet";
|
||||
}
|
||||
case PktErr::UNKNOWN_L3_PROTOCOL: {
|
||||
return os << "Unknown Layer 3 protocol type";
|
||||
}
|
||||
case PktErr::IP_SIZE_MISMATCH: {
|
||||
return os << "Wrong IP header size";
|
||||
}
|
||||
case PktErr::IP_VERSION_MISMATCH: {
|
||||
return os << "IP header version differs from the IP version defined by the Ethernet frame";
|
||||
}
|
||||
case PktErr::IP_HEADER_TOO_SMALL: {
|
||||
return os << "Reported IP header length is shorter than the allowed minimum";
|
||||
}
|
||||
case PktErr::PKT_TOO_SHORT_FOR_IP_HEADER: {
|
||||
return os << "Packet is too short for the IP header";
|
||||
}
|
||||
case PktErr::PKT_TOO_SHORT_FOR_IP_EXTENSION_HEADER: {
|
||||
return os << "Packet is too short for the IP extension header";
|
||||
}
|
||||
case PktErr::PKT_TOO_SHORT_FOR_IP_EXTENSION_HEADER_BODY: {
|
||||
return os << "Packet is too short for the IP extension body";
|
||||
}
|
||||
case PktErr::UNKNOWN_IPV6_EXTENSION_HEADER: {
|
||||
return os << "Unknown IPv6 extension";
|
||||
}
|
||||
case PktErr::PKT_TOO_SHORT_FOR_L4_HEADER: {
|
||||
return os << "IP content is too short to hold a Layer 4 header";
|
||||
}
|
||||
case PktErr::PKT_TOO_SHORT_FOR_TCP_OPTIONS: {
|
||||
return os << "IP content is too short to hold all the TCP Options";
|
||||
}
|
||||
case PktErr::TCP_HEADER_TOO_SMALL: {
|
||||
return os << "Reported TCP header length is shorter than the allowed minimum";
|
||||
}
|
||||
case PktErr::PKT_TOO_SHORT_FOR_ICMP_ERROR_DATA: {
|
||||
return os << "ICMP data is too short to hold all ICMP error information";
|
||||
}
|
||||
case PktErr::ICMP_VERSION_MISMATCH: {
|
||||
return os << "ICMP version does not match the IP version";
|
||||
}
|
||||
};
|
||||
|
||||
return os << "Unknown error: " << static_cast<uint>(err);
|
||||
}
|
||||
|
||||
// This is common for (almost) all extension headers.
|
||||
// All headers that ipv6_is_proto_extension returns true for them must have this layout
|
||||
struct IPv6ExtBasic
|
||||
{
|
||||
u_char next_type;
|
||||
};
|
||||
|
||||
// This is common for some extension headers
|
||||
struct IPv6ExtGeneric
|
||||
{
|
||||
u_char next_type;
|
||||
u_char ext_hdr_len; // Not in bytes! Sometimes *4, sometimes *8...
|
||||
};
|
||||
|
||||
static const uint basic_ext_len = 8;
|
||||
static const uint format_multiplier_four = 4;
|
||||
static const uint format_multiplier_eight = 8;
|
||||
static const char ipv4_chr = 0x40;
|
||||
static const char ipv6_chr = 0x60;
|
||||
static const char ipversion_mask = 0x60;
|
||||
|
||||
static bool
|
||||
isIPv6ProtoExtension(u_char proto)
|
||||
{
|
||||
// ESP and None are not considered as ext headers, as their first 4 bytes are not of type IPv6ExtBasic
|
||||
switch (proto) {
|
||||
case IPPROTO_HOPOPTS: // 0 IPv6 hop-by-hop options - RFC2460
|
||||
case IPPROTO_ROUTING: // 43 IPv6 routing header - RFC2460
|
||||
case IPPROTO_FRAGMENT: // 44 IPv6 fragmentation header - RFC2460
|
||||
// case IPPROTO_ESP: // 50 IPv6 encapsulation security payload header - RFC4303
|
||||
case IPPROTO_AH: // 51 IPv6 authentication header - RFC4302
|
||||
// case IPPROTO_NONE: // 59 IPv6 no next header - RFC2460
|
||||
case IPPROTO_DSTOPTS: // 60 IPv6 destination options - RFC2460
|
||||
case IPPROTO_MH: { // 135 IPv6 mobility header - RFC3775
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Maybe<ConnKey, PktErr>
|
||||
Packet::parseFromL4(const IPAddr &src, const IPAddr &dst, IPProto proto)
|
||||
{
|
||||
// Here so we got the l3 headers on both IPv4 and IPv6.
|
||||
if (is_fragment) return ConnKey(src, 0, dst, 0, proto);
|
||||
// Add ports
|
||||
PortNumber sport, dport;
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP: {
|
||||
auto maybe_tcp = l3_payload.getTypePtr<struct TcpHdr>(0);
|
||||
if (!maybe_tcp.ok()) {
|
||||
dbgTrace(D_PACKET)
|
||||
<< "TCP packet is too short ("
|
||||
<< l3_payload.size()
|
||||
<< ") to contain a basic TCP header";
|
||||
return genError(PktErr::PKT_TOO_SHORT_FOR_L4_HEADER);
|
||||
}
|
||||
auto tcp = maybe_tcp.unpack();
|
||||
auto l4_hdr_len = tcp->doff * sizeof(int32_t);
|
||||
|
||||
if (l4_hdr_len < sizeof(struct TcpHdr)) {
|
||||
dbgTrace(D_PACKET) <<
|
||||
"TCP header length is smaller than the minimum: " << l4_hdr_len << " < " << sizeof(struct tcphdr);
|
||||
return genError(PktErr::TCP_HEADER_TOO_SMALL);
|
||||
}
|
||||
if (l4_hdr_len > l3_payload.size()) {
|
||||
dbgTrace(D_PACKET) <<
|
||||
"TCP packet is too short (" << l3_payload.size() << ") for a TCP header (" << l4_hdr_len << ")";
|
||||
return genError(PktErr::PKT_TOO_SHORT_FOR_TCP_OPTIONS);
|
||||
}
|
||||
|
||||
l4_header = l3_payload.getSubBuffer(0, l4_hdr_len);
|
||||
l4_payload = l3_payload.getSubBuffer(l4_hdr_len, l3_payload.size());
|
||||
sport = ntohs(tcp->source);
|
||||
dport = ntohs(tcp->dest);
|
||||
break;
|
||||
}
|
||||
case IPPROTO_UDP: {
|
||||
auto maybe_udp = l3_payload.getTypePtr<struct UdpHdr>(0);
|
||||
if (!maybe_udp.ok()) {
|
||||
dbgTrace(D_PACKET)
|
||||
<< "UDP packet is too short ("
|
||||
<< l3_payload.size()
|
||||
<< ") to contain a basic UDP header";
|
||||
return genError(PktErr::PKT_TOO_SHORT_FOR_L4_HEADER);
|
||||
}
|
||||
auto udp = maybe_udp.unpack();
|
||||
auto l4_hdr_len = sizeof(struct UdpHdr);
|
||||
|
||||
l4_header = l3_payload.getSubBuffer(0, l4_hdr_len);
|
||||
l4_payload = l3_payload.getSubBuffer(l4_hdr_len, l3_payload.size());
|
||||
sport = ntohs(udp->source);
|
||||
dport = ntohs(udp->dest);
|
||||
break;
|
||||
}
|
||||
case IPPROTO_ICMP:
|
||||
case IPPROTO_ICMPV6: {
|
||||
auto icmp_hdr_len = getIcmpHdrLen(proto, src.getType());
|
||||
if (!icmp_hdr_len.ok()) return icmp_hdr_len.passErr();
|
||||
auto l4_hdr_len = icmp_hdr_len.unpack();
|
||||
if (l4_hdr_len > l3_payload.size()) {
|
||||
dbgTrace(D_PACKET)
|
||||
<< "ICMPv6 packet is too short ("
|
||||
<< l3_payload.size()
|
||||
<< ") to contain an ICMP header ("
|
||||
<< l4_hdr_len
|
||||
<< ")";
|
||||
return genError(PktErr::PKT_TOO_SHORT_FOR_L4_HEADER);
|
||||
}
|
||||
l4_header = l3_payload.getSubBuffer(0, l4_hdr_len);
|
||||
l4_payload = l3_payload.getSubBuffer(l4_hdr_len, l3_payload.size());
|
||||
tie(sport, dport) = getICMPPorts(proto);
|
||||
break;
|
||||
}
|
||||
case IPPROTO_GRE: {
|
||||
auto maybe_gre = l3_payload.getTypePtr<struct GreHdr>(0);
|
||||
if (!maybe_gre.ok()) {
|
||||
dbgTrace(D_PACKET)
|
||||
<< "GRE packet is too short ("
|
||||
<< l3_payload.size()
|
||||
<< ") to contain a basic GRE header";
|
||||
return genError(PktErr::PKT_TOO_SHORT_FOR_L4_HEADER);
|
||||
}
|
||||
auto l4_hdr_len = sizeof(struct GreHdr);
|
||||
|
||||
l4_header = l3_payload.getSubBuffer(0, l4_hdr_len);
|
||||
l4_payload = l3_payload.getSubBuffer(l4_hdr_len, l3_payload.size());
|
||||
sport = 0;
|
||||
dport = 0;
|
||||
break;
|
||||
}
|
||||
case IPPROTO_SCTP: {
|
||||
auto maybe_sctp = l3_payload.getTypePtr<struct SctpHdr>(0);
|
||||
if (!maybe_sctp.ok()) {
|
||||
dbgTrace(D_PACKET)
|
||||
<< "SCTP packet is too short ("
|
||||
<< l3_payload.size()
|
||||
<< ") to contain a basic SCTP header";
|
||||
return genError(PktErr::PKT_TOO_SHORT_FOR_L4_HEADER);
|
||||
}
|
||||
auto sctp = maybe_sctp.unpack();
|
||||
auto l4_hdr_len = sizeof(struct SctpHdr);
|
||||
|
||||
l4_header = l3_payload.getSubBuffer(0, l4_hdr_len);
|
||||
l4_payload = l3_payload.getSubBuffer(l4_hdr_len, l3_payload.size());
|
||||
sport = ntohs(sctp->sport);
|
||||
dport = ntohs(sctp->dport);
|
||||
break;
|
||||
}
|
||||
case IPPROTO_DCCP: {
|
||||
auto maybe_dccp = l3_payload.getTypePtr<struct DccpHdr>(0);
|
||||
if (!maybe_dccp.ok()) {
|
||||
dbgTrace(D_PACKET)
|
||||
<< "DCCP packet is too short ("
|
||||
<< l3_payload.size()
|
||||
<< ") to contain a basic DCCP header";
|
||||
return genError(PktErr::PKT_TOO_SHORT_FOR_L4_HEADER);
|
||||
}
|
||||
auto dccp = maybe_dccp.unpack();
|
||||
auto l4_hdr_len = sizeof(struct DccpHdr);
|
||||
|
||||
l4_header = l3_payload.getSubBuffer(0, l4_hdr_len);
|
||||
l4_payload = l3_payload.getSubBuffer(l4_hdr_len, l3_payload.size());
|
||||
sport = ntohs(dccp->dccph_sport);
|
||||
dport = ntohs(dccp->dccph_dport);
|
||||
break;
|
||||
}
|
||||
// other protocols
|
||||
default: {
|
||||
l4_payload = l3_payload;
|
||||
sport = 0;
|
||||
dport = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ConnKey(src, sport, dst, dport, proto);
|
||||
}
|
||||
|
||||
tuple<PortNumber, PortNumber>
|
||||
Packet::getICMPPortsV6()
|
||||
{
|
||||
auto icmp_hdr = l4_header.getTypePtr<struct icmp6_hdr>(0).unpack();
|
||||
PortNumber sport = 0;
|
||||
PortNumber dport = 0;
|
||||
switch(icmp_hdr->icmp6_type) {
|
||||
case ICMP6_ECHO_REQUEST:
|
||||
sport = ntohs(icmp_hdr->icmp6_id);
|
||||
if (!getConfigurationWithDefault<bool>(false, "Allow simultaneous ping")) {
|
||||
dport = ntohs(icmp_hdr->icmp6_seq);
|
||||
}
|
||||
break;
|
||||
case ICMP6_ECHO_REPLY:
|
||||
if (!getConfigurationWithDefault<bool>(false, "Allow simultaneous ping")) {
|
||||
sport = ntohs(icmp_hdr->icmp6_seq);
|
||||
}
|
||||
dport = ntohs(icmp_hdr->icmp6_id);
|
||||
break;
|
||||
case ICMP6_DST_UNREACH:
|
||||
case ICMP6_PACKET_TOO_BIG:
|
||||
case ICMP6_TIME_EXCEEDED:
|
||||
case ICMP6_PARAM_PROB:
|
||||
case ND_REDIRECT:
|
||||
sport = icmp_hdr->icmp6_code;
|
||||
dport = icmp_hdr->icmp6_type;
|
||||
break;
|
||||
}
|
||||
return make_tuple(sport, dport);
|
||||
}
|
||||
|
||||
tuple<PortNumber, PortNumber>
|
||||
Packet::getICMPPortsV4()
|
||||
{
|
||||
auto icmp_hdr = l4_header.getTypePtr<struct icmphdr>(0).unpack();
|
||||
PortNumber sport = 0;
|
||||
PortNumber dport = 0;
|
||||
switch(icmp_hdr->type) {
|
||||
case ICMP_ECHO:
|
||||
case ICMP_TSTAMP:
|
||||
case ICMP_IREQ:
|
||||
case ICMP_MASKREQ:
|
||||
sport = ntohs(icmp_hdr->un.echo.id);
|
||||
if (!getConfigurationWithDefault<bool>(false, "Allow simultaneous ping")) {
|
||||
dport = ntohs(icmp_hdr->un.echo.sequence);
|
||||
}
|
||||
break;
|
||||
case ICMP_ECHOREPLY:
|
||||
case ICMP_TSTAMPREPLY:
|
||||
case ICMP_IREQREPLY:
|
||||
case ICMP_MASKREPLY:
|
||||
if (!getConfigurationWithDefault<bool>(false, "Allow simultaneous ping")) {
|
||||
sport = ntohs(icmp_hdr->un.echo.sequence);
|
||||
}
|
||||
dport = ntohs(icmp_hdr->un.echo.id);
|
||||
break;
|
||||
case ICMP_UNREACH:
|
||||
case ICMP_SOURCEQUENCH:
|
||||
case ICMP_TIMXCEED:
|
||||
case ICMP_PARAMPROB:
|
||||
case ICMP_REDIRECT:
|
||||
sport = icmp_hdr->code;
|
||||
dport = icmp_hdr->type;
|
||||
break;
|
||||
}
|
||||
return make_tuple(sport, dport);
|
||||
}
|
||||
|
||||
tuple<PortNumber, PortNumber>
|
||||
Packet::getICMPPorts(IPProto proto)
|
||||
{
|
||||
return proto == IPPROTO_ICMP ? getICMPPortsV4() : getICMPPortsV6();
|
||||
}
|
||||
|
||||
Maybe<uint, PktErr>
|
||||
Packet::getIcmpHdrLen(IPProto proto, IPType ip_type)
|
||||
{
|
||||
if (proto == IPPROTO_ICMP && ip_type == IPType::V4) {
|
||||
return sizeof(struct icmphdr);
|
||||
} else if (proto == IPPROTO_ICMPV6 && ip_type == IPType::V6) {
|
||||
return sizeof(struct icmp6_hdr);
|
||||
}
|
||||
return genError(PktErr::ICMP_VERSION_MISMATCH);
|
||||
}
|
||||
|
||||
Maybe<int, PktErr>
|
||||
Packet::getIPv6GenericExtLen(uint offset_to_ext_hdr, uint length_multiplier)
|
||||
{
|
||||
auto maybe_header = l3.getTypePtr<IPv6ExtGeneric>(offset_to_ext_hdr);
|
||||
if (!maybe_header.ok()) {
|
||||
dbgTrace(D_PACKET) <<
|
||||
"Not enough room for an IPv6 Extension header basic data (" << offset_to_ext_hdr << " + " <<
|
||||
sizeof(IPv6ExtGeneric) << " > " << l3.size() << ")";
|
||||
return genError(PktErr::PKT_TOO_SHORT_FOR_IP_EXTENSION_HEADER);
|
||||
}
|
||||
auto header = maybe_header.unpack();
|
||||
|
||||
return basic_ext_len + (header->ext_hdr_len * length_multiplier);
|
||||
}
|
||||
|
||||
Maybe<int, PktErr>
|
||||
Packet::getIPv6ExtLen(uint offset_to_ext_hdr, IPProto ext_hdr_type)
|
||||
{
|
||||
switch (ext_hdr_type) {
|
||||
case IPPROTO_FRAGMENT: {
|
||||
// The length of Fragmentation and ESP headers is always 8 bytes. They don't have a length field.
|
||||
return basic_ext_len;
|
||||
}
|
||||
case IPPROTO_AH: {
|
||||
// In AH header the length field specifies the header's length in units of 4 bytes
|
||||
return getIPv6GenericExtLen(offset_to_ext_hdr, format_multiplier_four);
|
||||
}
|
||||
case IPPROTO_HOPOPTS:
|
||||
case IPPROTO_ROUTING:
|
||||
case IPPROTO_DSTOPTS:
|
||||
case IPPROTO_MH: {
|
||||
// For these headers, the length field specifies the header's length in units of 8 bytes
|
||||
return getIPv6GenericExtLen(offset_to_ext_hdr, format_multiplier_eight);
|
||||
}
|
||||
}
|
||||
dbgWarning(D_PACKET) << "Unknown IPv6 Extension header type" << static_cast<uint>(ext_hdr_type);
|
||||
return genError(PktErr::UNKNOWN_IPV6_EXTENSION_HEADER);
|
||||
}
|
||||
|
||||
Maybe<IPProto, PktErr>
|
||||
Packet::getIPv6Proto(IPProto proto)
|
||||
{
|
||||
uint offset_to_ext_hdr = sizeof(struct ip6_hdr);
|
||||
|
||||
while (isIPv6ProtoExtension(proto)) {
|
||||
auto res = getIPv6ExtLen(offset_to_ext_hdr, proto);
|
||||
if (!res.ok()) return res.passErr();
|
||||
auto ext_len = *res;
|
||||
|
||||
if (offset_to_ext_hdr + ext_len > l3.size()) {
|
||||
dbgTrace(D_PACKET) <<
|
||||
"IPv6 Extension header " << static_cast<uint>(proto) << " body is too long" <<
|
||||
" - Body length=" << ext_len << ", offset=" << offset_to_ext_hdr << ", L3 data length=" << l3.size();
|
||||
return genError(PktErr::PKT_TOO_SHORT_FOR_IP_EXTENSION_HEADER_BODY);
|
||||
}
|
||||
|
||||
if (proto == IPPROTO_FRAGMENT) {
|
||||
dbgTrace(D_PACKET) << "Fragmented IPv6 packet";
|
||||
is_fragment = true;
|
||||
}
|
||||
|
||||
auto header = l3.getTypePtr<IPv6ExtBasic>(offset_to_ext_hdr).unpack();
|
||||
proto = header->next_type;
|
||||
offset_to_ext_hdr += ext_len;
|
||||
}
|
||||
|
||||
l3_header = l3.getSubBuffer(0, offset_to_ext_hdr);
|
||||
l3_payload = l3.getSubBuffer(offset_to_ext_hdr, l3.size());
|
||||
return proto;
|
||||
}
|
||||
|
||||
Maybe<ConnKey, PktErr>
|
||||
Packet::parseFromL3v6()
|
||||
{
|
||||
auto maybe_ip6 = l2_payload.getTypePtr<struct ip6_hdr>(0);
|
||||
if (!maybe_ip6.ok()) {
|
||||
dbgTrace(D_PACKET)
|
||||
<< "IPv6 packet is too short for an IPv6 header: "
|
||||
<< l2_payload.size()
|
||||
<< " < "
|
||||
<< sizeof(struct ip);
|
||||
return genError(PktErr::PKT_TOO_SHORT_FOR_IP_HEADER);
|
||||
}
|
||||
auto ip6 = maybe_ip6.unpack();
|
||||
|
||||
uint ip_version = (ip6->ip6_vfc) >> 4;
|
||||
if (ip_version != 6) {
|
||||
dbgTrace(D_PACKET) << "Bad IPv6 version " << ip_version;
|
||||
return genError(PktErr::IP_VERSION_MISMATCH);
|
||||
}
|
||||
|
||||
auto l3_len_reported_by_header = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen);
|
||||
if (l3_len_reported_by_header > l2_payload.size()) {
|
||||
dbgTrace(D_PACKET) <<
|
||||
"IP header reports a total of " << l3_len_reported_by_header <<
|
||||
" bytes, but the packet length is only " << l2_payload.size() << " bytes";
|
||||
return genError(PktErr::IP_SIZE_MISMATCH);
|
||||
}
|
||||
|
||||
l3 = l2_payload.getSubBuffer(0, l3_len_reported_by_header); // Remove padding
|
||||
|
||||
auto proto = getIPv6Proto(ip6->ip6_nxt);
|
||||
if (!proto.ok()) return genError(proto.getErr());
|
||||
|
||||
return parseFromL4(IPAddr(ip6->ip6_src), IPAddr(ip6->ip6_dst), proto.unpack());
|
||||
}
|
||||
|
||||
Maybe<ConnKey, PktErr>
|
||||
Packet::parseFromL3v4()
|
||||
{
|
||||
auto maybe_ip4 = l2_payload.getTypePtr<struct ip>(0);
|
||||
if (!maybe_ip4.ok()) {
|
||||
dbgTrace(D_PACKET)
|
||||
<< "IPv4 packet is too short for an IPv4 header: "
|
||||
<< l2_payload.size()
|
||||
<< "<"
|
||||
<< sizeof(struct ip);
|
||||
return genError(PktErr::PKT_TOO_SHORT_FOR_IP_HEADER);
|
||||
}
|
||||
auto ip4 = maybe_ip4.unpack();
|
||||
|
||||
uint ip_version = ip4->ip_v;
|
||||
if (ip_version != 4) {
|
||||
dbgTrace(D_PACKET) << "Bad IPv4 version " << ip_version << " length: " << ntohs(ip4->ip_len);
|
||||
return genError(PktErr::IP_VERSION_MISMATCH);
|
||||
}
|
||||
|
||||
auto l3_len_reported_by_header = ntohs(ip4->ip_len);
|
||||
if (l3_len_reported_by_header < sizeof(struct ip)) {
|
||||
dbgTrace(D_PACKET) <<
|
||||
"IPv4 payload length is smaller than the IPv4 header: " <<
|
||||
l3_len_reported_by_header << " < " << sizeof(struct ip);
|
||||
return genError(PktErr::IP_SIZE_MISMATCH);
|
||||
}
|
||||
if (l3_len_reported_by_header > l2_payload.size()) {
|
||||
dbgTrace(D_PACKET) <<
|
||||
"IP header reports a total of " << l3_len_reported_by_header <<
|
||||
" bytes, but the packet length is only " << l2_payload.size() << " bytes";
|
||||
return genError(PktErr::IP_SIZE_MISMATCH);
|
||||
}
|
||||
|
||||
auto l3_hdr_len = ip4->ip_hl * sizeof(int);
|
||||
if (l3_hdr_len < sizeof(struct ip)) {
|
||||
dbgTrace(D_PACKET)
|
||||
<< "The reported IPv4 header length is smaller than the allowed minimum: "
|
||||
<< l3_hdr_len
|
||||
<< " < "
|
||||
<< sizeof(struct ip);
|
||||
return genError(PktErr::IP_HEADER_TOO_SMALL);
|
||||
}
|
||||
if (l3_hdr_len > l2_payload.size()) {
|
||||
dbgTrace(D_PACKET)
|
||||
<< "IPv4 header is too big for the IPv4 packet: "
|
||||
<< l3_hdr_len
|
||||
<< " > "
|
||||
<< l2_payload.size();
|
||||
return genError(PktErr::PKT_TOO_SHORT_FOR_IP_HEADER);
|
||||
}
|
||||
|
||||
auto frag_offset = ntohs(ip4->ip_off);
|
||||
if ((frag_offset & IP_OFFMASK) || (frag_offset & IP_MF)) {
|
||||
dbgTrace(D_PACKET) << "Fragmented IPv4 packet";
|
||||
is_fragment = true;
|
||||
}
|
||||
|
||||
l3 = l2_payload.getSubBuffer(0, l3_len_reported_by_header); // Remove padding
|
||||
l3_header = l3.getSubBuffer(0, l3_hdr_len);
|
||||
l3_payload = l3.getSubBuffer(l3_hdr_len, l3.size());
|
||||
|
||||
return parseFromL4(IPAddr(ip4->ip_src), IPAddr(ip4->ip_dst), ip4->ip_p);
|
||||
}
|
||||
|
||||
Maybe<ConnKey, PktErr>
|
||||
Packet::parseFromL2()
|
||||
{
|
||||
// In case of VLAN we want to remove the additional information and pass the packet as normal.
|
||||
uint _maclen = sizeof(struct ether_header) - 4; // -4 for the first do loop.
|
||||
uint16_t ether_type;
|
||||
do
|
||||
{
|
||||
_maclen += 4; // 4 is the size of vlan tag.
|
||||
auto maybe_ether_type = pkt_data.getTypePtr<uint16_t>(_maclen - 2); // Last 2 Bytes contain the ether type.
|
||||
if (!maybe_ether_type.ok()) {
|
||||
dbgTrace(D_PACKET)
|
||||
<< "VLAN tag length is greater than the packet length: "
|
||||
<< _maclen
|
||||
<< " > "
|
||||
<< pkt_data.size();
|
||||
return genError(PktErr::MAC_LEN_TOO_BIG);
|
||||
}
|
||||
ether_type = *(maybe_ether_type.unpack());
|
||||
} while (ether_type == constHTONS(ETHERTYPE_VLAN));
|
||||
|
||||
l2_header = pkt_data.getSubBuffer(0, _maclen);
|
||||
l2_payload = pkt_data.getSubBuffer(_maclen, pkt_data.size());
|
||||
|
||||
switch (ether_type) {
|
||||
case constHTONS(ETHERTYPE_IP): {
|
||||
return parseFromL3v4();
|
||||
}
|
||||
case constHTONS(ETHERTYPE_IPV6): {
|
||||
return parseFromL3v6();
|
||||
}
|
||||
default: {
|
||||
dbgTrace(D_PACKET) << "Unsupported Ethernet type: " << ether_type;
|
||||
return genError(PktErr::NON_IP_PACKET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<ConnKey, PktErr>
|
||||
Packet::parsePacket(PktType type, IPType proto)
|
||||
{
|
||||
if (type == PktType::PKT_L2) return parseFromL2();
|
||||
|
||||
l2_payload = pkt_data;
|
||||
switch (proto) {
|
||||
case IPType::V4: {
|
||||
return parseFromL3v4();
|
||||
}
|
||||
case IPType::V6: {
|
||||
return parseFromL3v6();
|
||||
}
|
||||
default: {
|
||||
dbgAssert(false) << "Unknown (neither IPv4, nor IPv6), or uninitialized packet type: " << proto;
|
||||
}
|
||||
}
|
||||
|
||||
return genError(PktErr::UNKNOWN_L3_PROTOCOL);
|
||||
}
|
||||
|
||||
std::vector<u_char>
|
||||
Packet::getL2DataVec() const
|
||||
{
|
||||
auto p = pkt_data.data();
|
||||
std::vector<u_char> buf(p, p+pkt_data.size());
|
||||
return buf;
|
||||
}
|
||||
|
||||
void
|
||||
Packet::setInterface(NetworkIfNum value)
|
||||
{
|
||||
interface = value;
|
||||
is_interface = true;
|
||||
}
|
||||
|
||||
void
|
||||
Packet::setZecoOpaque(u_int64_t value)
|
||||
{
|
||||
zeco_opaque = value;
|
||||
has_zeco_opaque = true;
|
||||
}
|
||||
|
||||
Maybe<NetworkIfNum>
|
||||
Packet::getInterface() const
|
||||
{
|
||||
if (!is_interface) return genError("Could not set an interface to send the packet");
|
||||
return interface;
|
||||
}
|
||||
|
||||
Maybe<u_int64_t>
|
||||
Packet::getZecoOpaque() const
|
||||
{
|
||||
if (!has_zeco_opaque) return genError("Could not get the zeco opaque");
|
||||
return zeco_opaque;
|
||||
}
|
7
components/packet/packet_ut/CMakeLists.txt
Normal file
7
components/packet/packet_ut/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
link_directories(${BOOST_ROOT}/lib)
|
||||
|
||||
add_unit_test(
|
||||
packet_ut
|
||||
"packet_ut.cc"
|
||||
"packet;connkey;buffers;environment;metric;event_is;-lboost_regex"
|
||||
)
|
844
components/packet/packet_ut/packet_ut.cc
Executable file
844
components/packet/packet_ut/packet_ut.cc
Executable file
@@ -0,0 +1,844 @@
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "cptest.h"
|
||||
#include "packet.h"
|
||||
#include "c_common/network_defs.h"
|
||||
#include "config.h"
|
||||
#include "config_component.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace testing;
|
||||
|
||||
// !!!!!!!!!! NOTE !!!!!!!!!!
|
||||
// If you are wondering how the hell to read the hex dumps, or how to make new tests -
|
||||
// Wireshark has an option (under the File menu) to import hex dumps.
|
||||
|
||||
static const uint mac_len = 14;
|
||||
static const uint ipv4_basic_hdr_size = 20;
|
||||
static const uint ipv6_basic_hdr_size = 40;
|
||||
static const uint tcp_basic_hdr_size = 20;
|
||||
static const uint udp_hdr_size = 8;
|
||||
|
||||
// Using IsError(Maybe<T>) requires T to be printable. So we need to print unique_ptr<Packet>:
|
||||
static ostream &
|
||||
operator<<(ostream &os, const unique_ptr<Packet> &p)
|
||||
{
|
||||
return os << "unique_ptr<Packet>(" << p.get() << ")";
|
||||
}
|
||||
|
||||
class PacketTest : public Test
|
||||
{
|
||||
public:
|
||||
ConnKey v4_key, v6_key;
|
||||
|
||||
PacketTest()
|
||||
:
|
||||
v4_key(
|
||||
IPAddr::createIPAddr("172.23.34.11").unpack(),
|
||||
0xae59,
|
||||
IPAddr::createIPAddr("172.23.53.31").unpack(),
|
||||
80,
|
||||
6
|
||||
),
|
||||
v6_key(
|
||||
IPAddr::createIPAddr("2001:6f8:102d:0:2d0:9ff:fee3:e8de").unpack(),
|
||||
59201,
|
||||
IPAddr::createIPAddr("2001:6f8:900:7c0::2").unpack(),
|
||||
80,
|
||||
6
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
Maybe<unique_ptr<Packet>, PktErr>
|
||||
getV4PacketL2()
|
||||
{
|
||||
// IPv4 TCP with 12 bytes of TCP options, 0 data
|
||||
auto v = cptestParseHex(
|
||||
"0000: cc d8 c1 b1 cc 77 00 50 56 b9 4f 5c 08 00 45 00 "
|
||||
"0010: 00 34 93 24 40 00 40 06 f8 46 ac 17 22 0b ac 17 "
|
||||
"0020: 35 1f ae 59 00 50 1a bb 79 14 5f 45 dc 97 80 10 "
|
||||
"0030: 00 6c 1a 8c 00 00 01 01 08 0a ff fe eb 97 68 00 "
|
||||
"0040: da 7e "
|
||||
);
|
||||
return Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
}
|
||||
|
||||
Maybe<unique_ptr<Packet>, PktErr>
|
||||
getV4PacketL3()
|
||||
{
|
||||
// IPv4 TCP with 12 bytes of TCP options, 0 data
|
||||
auto v = cptestParseHex(
|
||||
"0000: 45 00 00 34 93 24 40 00 40 06 f8 46 ac 17 22 0b "
|
||||
"0010: ac 17 35 1f ae 59 00 50 1a bb 79 14 5f 45 dc 97 "
|
||||
"0020: 80 10 00 6c 1a 8c 00 00 01 01 08 0a ff fe eb 97 "
|
||||
"0030: 68 00 da 7e "
|
||||
);
|
||||
return Packet::genPacket(PktType::PKT_L3, IPType::V4, v);
|
||||
}
|
||||
|
||||
Maybe<unique_ptr<Packet>, PktErr>
|
||||
getV6PacketL2()
|
||||
{
|
||||
// IPv6 TCP with 20 bytes of TCP options, 0 data
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 11 25 82 95 b5 00 d0 09 e3 e8 de 86 dd 60 00 "
|
||||
"0010: 00 00 00 28 06 40 20 01 06 f8 10 2d 00 00 02 d0 "
|
||||
"0020: 09 ff fe e3 e8 de 20 01 06 f8 09 00 07 c0 00 00 "
|
||||
"0030: 00 00 00 00 00 02 e7 41 00 50 ab dc d6 60 00 00 "
|
||||
"0040: 00 00 a0 02 16 80 41 a2 00 00 02 04 05 a0 04 02 "
|
||||
"0050: 08 0a 00 0a 22 a8 00 00 00 00 01 03 03 05 "
|
||||
);
|
||||
return Packet::genPacket(PktType::PKT_L2, IPType::V6, v);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(PacketTest, check_zeco_opaque)
|
||||
{
|
||||
auto v4_pkt = getV4PacketL2().unpackMove();
|
||||
auto zeco_opaque = v4_pkt->getZecoOpaque();
|
||||
EXPECT_FALSE(zeco_opaque.ok());
|
||||
|
||||
v4_pkt->setZecoOpaque(11);
|
||||
|
||||
zeco_opaque = v4_pkt->getZecoOpaque();
|
||||
EXPECT_TRUE(zeco_opaque.ok());
|
||||
EXPECT_EQ(zeco_opaque.unpack(), 11u);
|
||||
}
|
||||
|
||||
TEST_F(PacketTest, check_fixture_ctor)
|
||||
{
|
||||
EXPECT_TRUE(getV4PacketL2().ok());
|
||||
EXPECT_TRUE(getV6PacketL2().ok());
|
||||
}
|
||||
|
||||
TEST_F(PacketTest, l2_v4_good)
|
||||
{
|
||||
auto v4_pkt = getV4PacketL2().unpackMove();
|
||||
EXPECT_EQ(v4_pkt->getPacket().size(), mac_len + 52);
|
||||
EXPECT_EQ(v4_pkt->getL3().size(), 52u);
|
||||
EXPECT_EQ(v4_pkt->getL3Header().size(), ipv4_basic_hdr_size);
|
||||
EXPECT_EQ(v4_pkt->getL4Header().size(), tcp_basic_hdr_size + 12);
|
||||
Buffer l2_buf = v4_pkt->getPacket();
|
||||
l2_buf.truncateHead(mac_len);
|
||||
EXPECT_EQ(v4_pkt->getL3(), l2_buf);
|
||||
EXPECT_EQ(v4_pkt->getKey(), v4_key);
|
||||
}
|
||||
|
||||
TEST_F(PacketTest, l3_v4_good)
|
||||
{
|
||||
auto v4_pkt = getV4PacketL3().unpackMove();
|
||||
EXPECT_EQ(v4_pkt->getPacket().size(), 52u);
|
||||
EXPECT_EQ(v4_pkt->getL3().size(), 52u);
|
||||
EXPECT_EQ(v4_pkt->getL3Header().size(), ipv4_basic_hdr_size);
|
||||
EXPECT_EQ(v4_pkt->getL4Header().size(), tcp_basic_hdr_size + 12);
|
||||
Buffer l2_buf = v4_pkt->getPacket();
|
||||
EXPECT_EQ(v4_pkt->getL3(), l2_buf);
|
||||
EXPECT_EQ(v4_pkt->getKey(), v4_key);
|
||||
}
|
||||
|
||||
TEST_F(PacketTest, v6_good)
|
||||
{
|
||||
auto v6_pkt = getV6PacketL2().unpackMove();
|
||||
EXPECT_EQ(v6_pkt->getPacket().size(), mac_len + 80);
|
||||
EXPECT_EQ(v6_pkt->getL3().size(), 80u);
|
||||
EXPECT_EQ(v6_pkt->getL3Header().size(), ipv6_basic_hdr_size);
|
||||
EXPECT_EQ(v6_pkt->getL4Header().size(), tcp_basic_hdr_size + 20);
|
||||
Buffer l2_buf = v6_pkt->getPacket();
|
||||
l2_buf.truncateHead(mac_len);
|
||||
EXPECT_EQ(v6_pkt->getL3(), l2_buf);
|
||||
EXPECT_EQ(v6_pkt->getKey(), v6_key);
|
||||
}
|
||||
|
||||
TEST_F(PacketTest, l2_v4_get_l4)
|
||||
{
|
||||
auto v4_pkt = getV4PacketL2().unpackMove();
|
||||
Buffer buf = v4_pkt->getL4Data();
|
||||
EXPECT_EQ(buf.size(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(PacketTest, l3_v4_get_l4)
|
||||
{
|
||||
auto v4_pkt = getV4PacketL3().unpackMove();
|
||||
Buffer buf = v4_pkt->getL4Data();
|
||||
EXPECT_EQ(buf.size(), 0u);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(PacketTest, v6_get_l4)
|
||||
{
|
||||
auto v6_pkt = getV6PacketL2().unpackMove();
|
||||
Buffer buf = v6_pkt->getL4Data();
|
||||
EXPECT_EQ(buf.size(), 0u);
|
||||
}
|
||||
|
||||
TEST(Packet, packet_with_padding)
|
||||
{
|
||||
ConnKey ck(
|
||||
IPAddr::createIPAddr("192.168.170.8").unpack(),
|
||||
32795,
|
||||
IPAddr::createIPAddr("192.168.170.20").unpack(),
|
||||
53,
|
||||
17
|
||||
);
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 c0 9f 32 41 8c 00 e0 18 b1 0c ad 08 00 45 00 "
|
||||
"0010: 00 3d 00 00 40 00 40 11 65 42 c0 a8 aa 08 c0 a8 "
|
||||
"0020: aa 14 80 1b 00 35 00 29 88 61 bc 1f 01 00 00 01 "
|
||||
"0030: 00 00 00 00 00 00 03 77 77 77 07 65 78 61 6d 70 "
|
||||
"0040: 6c 65 03 63 6f 6d 00 00 1c 00 01 00 00 00 00 00 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
ASSERT_TRUE(ptr.ok());
|
||||
auto p = ptr.unpackMove();
|
||||
|
||||
EXPECT_EQ(p->getL3().size(), 61u); // True size as reported by IP header.
|
||||
EXPECT_EQ(p->getL3Header().size(), ipv4_basic_hdr_size);
|
||||
EXPECT_EQ(p->getL4Header().size(), udp_hdr_size);
|
||||
EXPECT_EQ(p->getKey(), ck);
|
||||
EXPECT_EQ(p->getL4Data().size(), 33u);
|
||||
}
|
||||
|
||||
|
||||
TEST(Packet, v4_ip_options)
|
||||
{
|
||||
ConnKey ck(
|
||||
IPAddr::createIPAddr("172.23.34.11").unpack(),
|
||||
44633,
|
||||
IPAddr::createIPAddr("172.23.53.31").unpack(),
|
||||
80,
|
||||
6
|
||||
);
|
||||
auto v = cptestParseHex(
|
||||
"0000: cc d8 c1 b1 cc 77 00 50 56 b9 4f 5c 08 00 47 00 " // Modified: 4500 => 4700 for 2 option ints.
|
||||
"0010: 00 3c 93 24 40 00 40 06 f8 46 ac 17 22 0b ac 17 "
|
||||
"0020: 35 1f 01 04 12 34 56 78 00 00 ae 59 00 50 1a bb " // Inserted IP options: NOP; EOL;
|
||||
"0030: 79 14 5f 45 dc 97 80 10 00 6c 1a 8c 00 00 01 01 "
|
||||
"0040: 08 0a ff fe eb 97 68 00 da 7e "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
ASSERT_TRUE(ptr.ok());
|
||||
auto p = ptr.unpackMove();
|
||||
|
||||
EXPECT_EQ(p->getKey(), ck);
|
||||
EXPECT_EQ(p->getL3().size(), 60u);
|
||||
EXPECT_EQ(p->getL3Header().size(), ipv4_basic_hdr_size + 8); // 8 bytes IP options
|
||||
EXPECT_EQ(p->getL4Header().size(), tcp_basic_hdr_size + 12); // 12 bytes TCP options
|
||||
|
||||
// Get L4 fields
|
||||
EXPECT_EQ(p->getL4Data().size(), 0u);
|
||||
}
|
||||
|
||||
TEST(Packet, l2_v4_udp)
|
||||
{
|
||||
ConnKey ck(
|
||||
IPAddr::createIPAddr("192.168.170.8").unpack(),
|
||||
32795,
|
||||
IPAddr::createIPAddr("192.168.170.20").unpack(),
|
||||
53,
|
||||
17
|
||||
);
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 c0 9f 32 41 8c 00 e0 18 b1 0c ad 08 00 45 00 "
|
||||
"0010: 00 3d 00 00 40 00 40 11 65 42 c0 a8 aa 08 c0 a8 "
|
||||
"0020: aa 14 80 1b 00 35 00 29 88 61 bc 1f 01 00 00 01 "
|
||||
"0030: 00 00 00 00 00 00 03 77 77 77 07 65 78 61 6d 70 "
|
||||
"0040: 6c 65 03 63 6f 6d 00 00 1c 00 01 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
ASSERT_TRUE(ptr.ok());
|
||||
auto p = ptr.unpackMove();
|
||||
|
||||
EXPECT_EQ(p->getL3().size(), 61u);
|
||||
EXPECT_EQ(p->getL3Header().size(), ipv4_basic_hdr_size);
|
||||
EXPECT_EQ(p->getL4Header().size(), udp_hdr_size);
|
||||
EXPECT_EQ(p->getKey(), ck);
|
||||
|
||||
EXPECT_EQ(p->getL4Data().size(), 33u);
|
||||
}
|
||||
|
||||
TEST(Packet, l3_v4_udp)
|
||||
{
|
||||
ConnKey ck(
|
||||
IPAddr::createIPAddr("192.168.170.8").unpack(),
|
||||
32795,
|
||||
IPAddr::createIPAddr("192.168.170.20").unpack(),
|
||||
53,
|
||||
17
|
||||
);
|
||||
auto v = cptestParseHex(
|
||||
"0000: 45 00 00 3d 00 00 40 00 40 11 65 42 c0 a8 aa 08 "
|
||||
"0010: c0 a8 aa 14 80 1b 00 35 00 29 88 61 bc 1f 01 00 "
|
||||
"0020: 00 01 00 00 00 00 00 00 03 77 77 77 07 65 78 61 "
|
||||
"0030: 6d 70 6c 65 03 63 6f 6d 00 00 1c 00 01 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L3, IPType::V4, v);
|
||||
ASSERT_TRUE(ptr.ok());
|
||||
auto p = ptr.unpackMove();
|
||||
|
||||
EXPECT_EQ(p->getL3().size(), 61u);
|
||||
EXPECT_EQ(p->getL3Header().size(), ipv4_basic_hdr_size);
|
||||
EXPECT_EQ(p->getL4Header().size(), udp_hdr_size);
|
||||
EXPECT_EQ(p->getKey(), ck);
|
||||
|
||||
EXPECT_EQ(p->getL4Data().size(), 33u);
|
||||
}
|
||||
|
||||
TEST(Packet, v6_ping)
|
||||
{
|
||||
::Environment env;
|
||||
ConfigComponent config_comp;
|
||||
ConnKey ck(
|
||||
IPAddr::createIPAddr("3ffe:507:0:1:200:86ff:fe05:80da").unpack(),
|
||||
31520,
|
||||
IPAddr::createIPAddr("3ffe:507:0:1:260:97ff:fe07:69ea").unpack(),
|
||||
1024,
|
||||
58
|
||||
);
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 60 97 07 69 ea 00 00 86 05 80 da 86 dd 60 00 "
|
||||
"0010: 00 00 00 10 3a 40 3f fe 05 07 00 00 00 01 02 00 "
|
||||
"0020: 86 ff fe 05 80 da 3f fe 05 07 00 00 00 01 02 60 "
|
||||
"0030: 97 ff fe 07 69 ea 80 00 ae 76 7b 20 04 00 1d c9 "
|
||||
"0040: e7 36 ad df 0b 00 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V6, v);
|
||||
ASSERT_TRUE(ptr.ok());
|
||||
auto p = ptr.unpackMove();
|
||||
|
||||
EXPECT_EQ(p->getL3().size(), 56u);
|
||||
EXPECT_EQ(p->getL3Header().size(), ipv6_basic_hdr_size);
|
||||
EXPECT_EQ(p->getL4Header().size(), sizeof(struct icmp6_hdr));
|
||||
EXPECT_EQ(p->getKey(), ck);
|
||||
}
|
||||
|
||||
TEST(Packet, v6_IPPROTO_ROUTING_extension_hdr)
|
||||
{
|
||||
// IPv6 TCP packet with IPPROTO_ROUTING extension header (56 bytes), 20 bytes of data
|
||||
ConnKey ck(
|
||||
IPAddr::createIPAddr("3001::200:1080:8110:11fe").unpack(),
|
||||
32768,
|
||||
IPAddr::createIPAddr("3000::215:1780:8116:b881").unpack(),
|
||||
80,
|
||||
6
|
||||
);
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 60 97 07 69 ea 00 00 86 05 80 da 86 dd 60 00 "
|
||||
"0010: 00 00 00 60 2b 80 30 01 00 00 00 00 00 00 02 00 "
|
||||
"0020: 10 80 81 10 11 fe 30 00 00 00 00 00 00 00 02 15 "
|
||||
"0030: 17 80 81 16 b8 81 06 06 00 01 00 00 00 00 30 02 "
|
||||
"0040: 00 00 00 00 00 00 02 00 10 80 81 10 12 62 30 03 "
|
||||
"0050: 00 00 00 00 00 00 02 00 10 80 81 10 10 60 ff 00 "
|
||||
"0060: 1d 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 "
|
||||
"0070: 00 50 11 11 11 11 22 22 22 22 50 18 67 68 2b d2 "
|
||||
"0080: 00 00 6d 6e 6f 70 71 72 73 74 75 76 77 61 62 63 "
|
||||
"0090: 64 65 66 67 68 69 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V6, v);
|
||||
ASSERT_TRUE(ptr.ok());
|
||||
auto p = ptr.unpackMove();
|
||||
|
||||
static const uint routing_ext_hdr_size = 56;
|
||||
static const uint total_packet_len = 150;
|
||||
|
||||
EXPECT_EQ(p->getPacket().size(), total_packet_len);
|
||||
EXPECT_EQ(p->getL3().size(), total_packet_len - mac_len);
|
||||
EXPECT_EQ(p->getL3Header().size(), ipv6_basic_hdr_size + routing_ext_hdr_size);
|
||||
EXPECT_EQ(p->getL4Header().size(), tcp_basic_hdr_size);
|
||||
EXPECT_EQ(p->getKey(), ck);
|
||||
EXPECT_EQ(p->getL4Data().size(), 20u);
|
||||
}
|
||||
|
||||
|
||||
TEST(Packet, v6_IPPROTO_HOPOPT_and_IPPROTO_ROUTING_ext_hdrs)
|
||||
{
|
||||
ConnKey ck(
|
||||
IPAddr::createIPAddr("3001::200:1080:8110:11fe").unpack(),
|
||||
32768,
|
||||
IPAddr::createIPAddr("3000::215:1780:8116:b881").unpack(),
|
||||
58205,
|
||||
17
|
||||
);
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 60 97 07 69 ea 00 00 86 05 80 da 86 dd 60 00 "
|
||||
"0010: 00 00 00 70 00 80 30 01 00 00 00 00 00 00 02 00 "
|
||||
"0020: 10 80 81 10 11 fe 30 00 00 00 00 00 00 00 02 15 "
|
||||
"0030: 17 80 81 16 b8 81 2b 01 00 00 00 00 00 00 00 00 "
|
||||
"0040: 00 00 00 00 00 00 11 06 00 01 00 00 00 00 30 02 "
|
||||
"0050: 00 00 00 00 00 00 02 00 10 80 81 10 12 62 30 03 "
|
||||
"0060: 00 00 00 00 00 00 02 00 10 80 81 10 10 60 ff 00 "
|
||||
"0070: 1d 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 "
|
||||
"0080: e3 5d 00 28 00 0c 61 62 63 64 65 66 67 68 69 6a "
|
||||
"0090: 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 61 62 63 "
|
||||
"00a0: 64 65 66 67 68 69 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V6, v);
|
||||
ASSERT_TRUE(ptr.ok());
|
||||
auto p = ptr.unpackMove();
|
||||
|
||||
static const uint routing_ext_hdr_size = 56;
|
||||
static const uint hop_ext_hdr_size = 16;
|
||||
static const uint total_packet_len = 166;
|
||||
static const uint total_extensions_size = routing_ext_hdr_size + hop_ext_hdr_size;
|
||||
|
||||
EXPECT_EQ(p->getPacket().size(), total_packet_len);
|
||||
EXPECT_EQ(p->getL3().size(), total_packet_len - mac_len);
|
||||
EXPECT_EQ(p->getL3Header().size(), ipv6_basic_hdr_size + total_extensions_size);
|
||||
EXPECT_EQ(p->getL4Header().size(), udp_hdr_size);
|
||||
EXPECT_EQ(p->getKey(), ck);
|
||||
|
||||
EXPECT_EQ(p->getL4Data().size(), 32u);
|
||||
}
|
||||
|
||||
TEST(Packet, DISABLED_non_ethernet_mac_len)
|
||||
{
|
||||
auto v = cptestParseHex(
|
||||
"0000: cc d8 c1 b1 cc 77 00 50 56 b9 4f 5c 08 00 45 00 "
|
||||
"0010: 00 34 93 24 40 00 40 06 f8 46 ac 17 22 0b ac 17 "
|
||||
"0020: 35 1f ae 59 00 50 1a bb 79 14 5f 45 dc 97 80 10 "
|
||||
"0030: 00 6c 1a 8c 00 00 01 01 08 0a ff fe eb 97 68 00 "
|
||||
"0040: da 7e "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::NON_ETHERNET_FRAME));
|
||||
}
|
||||
|
||||
TEST(Packet, DISABLED_too_big_mac_len)
|
||||
{
|
||||
auto v = cptestParseHex(
|
||||
"0000: cc d8 c1 b1 cc 77 00 50 56 b9 4f 5c 08 00 45 00 "
|
||||
"0010: 00 34 93 24 40 00 40 06 f8 46 ac 17 22 0b ac 17 "
|
||||
"0020: 35 1f ae 59 00 50 1a bb 79 14 5f 45 dc 97 80 10 "
|
||||
"0030: 00 6c 1a 8c 00 00 01 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::MAC_LEN_TOO_BIG));
|
||||
}
|
||||
|
||||
TEST(Packet, non_ip_packet)
|
||||
{
|
||||
auto v = cptestParseHex(
|
||||
"0000: cc d8 c1 b1 cc 77 00 50 56 b9 4f 5c 08 88 45 00 "
|
||||
"0010: 00 34 93 24 40 00 40 06 f8 46 ac 17 22 0b ac 17 "
|
||||
"0020: 35 1f ae 59 00 50 1a bb 79 14 5f 45 dc 97 80 10 "
|
||||
"0030: 00 6c 1a 8c 00 00 01 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::NON_IP_PACKET));
|
||||
}
|
||||
|
||||
TEST(Packet, version_mismatch_v4)
|
||||
{
|
||||
// Valid IPv4 packet, but Ethernet header says it is IPv6
|
||||
auto v = cptestParseHex(
|
||||
"0000: cc d8 c1 b1 cc 77 00 50 56 b9 4f 5c 86 dd 45 00 "
|
||||
"0010: 00 34 93 24 40 00 40 06 f8 46 ac 17 22 0b ac 17 "
|
||||
"0020: 35 1f ae 59 00 50 1a bb 79 14 5f 45 dc 97 80 10 "
|
||||
"0030: 00 6c 1a 8c 00 00 01 01 08 0a ff fe eb 97 68 00 "
|
||||
"0040: da 7e "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::IP_VERSION_MISMATCH));
|
||||
}
|
||||
|
||||
TEST(Packet, version_mismatch_v6)
|
||||
{
|
||||
// Valid IPv6 packet, but Ethernet header says it is IPv4
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 11 25 82 95 b5 00 d0 09 e3 e8 de 08 00 60 00 "
|
||||
"0010: 00 00 00 28 06 40 20 01 06 f8 10 2d 00 00 02 d0 "
|
||||
"0020: 09 ff fe e3 e8 de 20 01 06 f8 09 00 07 c0 00 00 "
|
||||
"0030: 00 00 00 00 00 02 e7 41 00 50 ab dc d6 60 00 00 "
|
||||
"0040: 00 00 a0 02 16 80 41 a2 00 00 02 04 05 a0 04 02 "
|
||||
"0050: 08 0a 00 0a 22 a8 00 00 00 00 01 03 03 05 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V6, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::IP_VERSION_MISMATCH));
|
||||
}
|
||||
|
||||
TEST(Packet, empty_frame_v4)
|
||||
{
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 c0 9f 32 41 8c 00 e0 18 b1 0c ad 08 00 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::PKT_TOO_SHORT_FOR_IP_HEADER));
|
||||
}
|
||||
|
||||
TEST(Packet, empty_frame_v6)
|
||||
{
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 c0 9f 32 41 8c 00 e0 18 b1 0c ad 86 dd "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::PKT_TOO_SHORT_FOR_IP_HEADER));
|
||||
}
|
||||
|
||||
TEST(Packet, ipv4_pkt_no_room_for_header)
|
||||
{
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 c0 9f 32 41 8c 00 e0 18 b1 0c ad 08 00 45 00 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::PKT_TOO_SHORT_FOR_IP_HEADER));
|
||||
}
|
||||
|
||||
TEST(Packet, ipv4_pkt_no_room_for_header_with_options)
|
||||
{
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 c0 9f 32 41 8c 00 e0 18 b1 0c ad 08 00 48 00 "
|
||||
"0010: 00 1c 00 00 40 00 40 11 65 42 c0 a8 aa 08 c0 a8 "
|
||||
"0020: aa 14 80 1b 00 35 00 29 88 61 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::PKT_TOO_SHORT_FOR_IP_HEADER));
|
||||
}
|
||||
|
||||
TEST(Packet, ipv6_pkt_no_room_for_header)
|
||||
{
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 c0 9f 32 41 8c 00 e0 18 b1 0c ad 86 dd 60 00 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V6, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::PKT_TOO_SHORT_FOR_IP_HEADER));
|
||||
}
|
||||
|
||||
TEST(Packet, ipv4_payload_length_smaller_than_ipv4_header)
|
||||
{
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 c0 9f 32 41 8c 00 e0 18 b1 0c ad 08 00 45 00 "
|
||||
"0010: 00 10 00 00 40 00 40 11 65 42 c0 a8 aa 08 c0 a8 "
|
||||
"0020: aa 14 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::IP_SIZE_MISMATCH));
|
||||
}
|
||||
|
||||
TEST(Packet, v6_ext_hdr_not_complete)
|
||||
{
|
||||
// IPv6 packet with IPPROTO_HOPOPTS cut at the middle of the header
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 60 97 07 69 ea 00 00 86 05 80 da 86 dd 60 00 "
|
||||
"0010: 00 00 00 01 00 80 30 01 00 00 00 00 00 00 02 00 "
|
||||
"0020: 10 80 81 10 11 fe 30 00 00 00 00 00 00 00 02 15 "
|
||||
"0030: 17 80 81 16 b8 81 3a "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V6, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::PKT_TOO_SHORT_FOR_IP_EXTENSION_HEADER));
|
||||
}
|
||||
|
||||
|
||||
TEST(Packet, v6_no_room_for_ext_hdr_body)
|
||||
{
|
||||
// IPv6 packet with IPPROTO_HOPOPTS ext header specified as 16 bytes, but packet too short
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 60 97 07 69 ea 00 00 86 05 80 da 86 dd 60 00 "
|
||||
"0010: 00 00 00 02 00 80 30 01 00 00 00 00 00 00 02 00 "
|
||||
"0020: 10 80 81 10 11 fe 30 00 00 00 00 00 00 00 02 15 "
|
||||
"0030: 17 80 81 16 b8 81 3a 01 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V6, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::PKT_TOO_SHORT_FOR_IP_EXTENSION_HEADER_BODY));
|
||||
}
|
||||
|
||||
|
||||
TEST(Packet, ipv4_size_mismatch)
|
||||
{
|
||||
auto v = cptestParseHex(
|
||||
"0000: cc d8 c1 b1 cc 77 00 50 56 b9 4f 5c 08 00 45 00 "
|
||||
"0010: 00 35 93 24 40 00 40 06 f8 46 ac 17 22 0b ac 17 "
|
||||
"0020: 35 1f ae 59 00 50 1a bb 79 14 5f 45 dc 97 80 10 "
|
||||
"0030: 00 6c 1a 8c 00 00 01 01 08 0a ff fe eb 97 68 00 "
|
||||
"0040: da 7e "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::IP_SIZE_MISMATCH));
|
||||
}
|
||||
|
||||
TEST(Packet, ipv6_size_mismatch)
|
||||
{
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 11 25 82 95 b5 00 d0 09 e3 e8 de 86 dd 60 00 "
|
||||
"0010: 00 00 00 29 06 40 20 01 06 f8 10 2d 00 00 02 d0 "
|
||||
"0020: 09 ff fe e3 e8 de 20 01 06 f8 09 00 07 c0 00 00 "
|
||||
"0030: 00 00 00 00 00 02 e7 41 00 50 ab dc d6 60 00 00 "
|
||||
"0040: 00 00 a0 02 16 80 41 a2 00 00 02 04 05 a0 04 02 "
|
||||
"0050: 08 0a 00 0a 22 a8 00 00 00 00 01 03 03 05 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V6, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::IP_SIZE_MISMATCH));
|
||||
}
|
||||
|
||||
|
||||
TEST(Packet, no_room_for_udp_header)
|
||||
{
|
||||
auto v = cptestParseHex(
|
||||
"0000: cc d8 c1 b1 cc 77 00 50 56 b9 4f 5c 08 00 45 00 "
|
||||
"0010: 00 18 93 24 40 00 40 11 f8 57 ac 17 22 0b ac 17 "
|
||||
"0020: 35 1f ae 59 00 50 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::PKT_TOO_SHORT_FOR_L4_HEADER));
|
||||
}
|
||||
|
||||
TEST(Packet, no_room_for_tcp_header)
|
||||
{
|
||||
auto v = cptestParseHex(
|
||||
"0000: cc d8 c1 b1 cc 77 00 50 56 b9 4f 5c 08 00 45 00 "
|
||||
"0010: 00 22 93 24 40 00 40 06 f8 58 ac 17 22 0b ac 17 "
|
||||
"0020: 35 1f ae 59 00 50 1a bb 79 14 5f 45 dc 97 80 10 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::PKT_TOO_SHORT_FOR_L4_HEADER));
|
||||
}
|
||||
|
||||
TEST(Packet, tcp_header_len_too_short)
|
||||
{
|
||||
auto v = cptestParseHex(
|
||||
"0000: cc d8 c1 b1 cc 77 00 50 56 b9 4f 5c 08 00 45 00 "
|
||||
"0010: 00 28 93 24 40 00 40 06 f8 52 ac 17 22 0b ac 17 "
|
||||
"0020: 35 1f ae 59 00 50 1a bb 79 14 5f 45 dc 97 20 10 "
|
||||
"0030: 00 6c 1a 8c 00 00 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::TCP_HEADER_TOO_SMALL));
|
||||
}
|
||||
|
||||
|
||||
TEST(Packet, tcp_header_len_too_big)
|
||||
{
|
||||
auto v = cptestParseHex(
|
||||
"0000: cc d8 c1 b1 cc 77 00 50 56 b9 4f 5c 08 00 45 00 "
|
||||
"0010: 00 29 93 24 40 00 40 06 f8 51 ac 17 22 0b ac 17 "
|
||||
"0020: 35 1f ae 59 00 50 1a bb 79 14 5f 45 dc 97 80 10 "
|
||||
"0030: 00 6c 1a 8c 00 00 01 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::PKT_TOO_SHORT_FOR_TCP_OPTIONS));
|
||||
}
|
||||
|
||||
TEST(Packet, get_l2_data_vec)
|
||||
{
|
||||
auto v = cptestParseHex( // Same as v4_udp
|
||||
"0000: 00 c0 9f 32 41 8c 00 e0 18 b1 0c ad 08 00 45 00 "
|
||||
"0010: 00 3d 00 00 40 00 40 11 65 42 c0 a8 aa 08 c0 a8 "
|
||||
"0020: aa 14 80 1b 00 35 00 29 88 61 bc 1f 01 00 00 01 "
|
||||
"0030: 00 00 00 00 00 00 03 77 77 77 07 65 78 61 6d 70 "
|
||||
"0040: 6c 65 03 63 6f 6d 00 00 1c 00 01 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
|
||||
EXPECT_EQ(v, (*ptr)->getL2DataVec());
|
||||
}
|
||||
|
||||
TEST(Packet, interface_set_and_get)
|
||||
{
|
||||
auto v = cptestParseHex( // Same as v4_udp
|
||||
"0000: 00 c0 9f 32 41 8c 00 e0 18 b1 0c ad 08 00 45 00 "
|
||||
"0010: 00 3d 00 00 40 00 40 11 65 42 c0 a8 aa 08 c0 a8 "
|
||||
"0020: aa 14 80 1b 00 35 00 29 88 61 bc 1f 01 00 00 01 "
|
||||
"0030: 00 00 00 00 00 00 03 77 77 77 07 65 78 61 6d 70 "
|
||||
"0040: 6c 65 03 63 6f 6d 00 00 1c 00 01 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
auto p = ptr.unpackMove();
|
||||
|
||||
EXPECT_FALSE(p->getInterface().ok());
|
||||
|
||||
p->setInterface(5);
|
||||
EXPECT_TRUE(p->getInterface().ok());
|
||||
EXPECT_EQ(5, p->getInterface().unpack());
|
||||
|
||||
p->setInterface(42);
|
||||
EXPECT_TRUE(p->getInterface().ok());
|
||||
EXPECT_EQ(42, p->getInterface().unpack());
|
||||
}
|
||||
|
||||
TEST(Packet, no_room_for_icmp_header)
|
||||
{
|
||||
// only 7 bytes of ICMPV4 (min is 8)
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 "
|
||||
"0010: 00 1b 12 34 40 00 ff 01 6b ab 7f 00 00 01 7f 00 "
|
||||
"0020: 00 01 00 00 ff fd 00 01 00 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
ASSERT_FALSE(ptr.ok());
|
||||
EXPECT_EQ(ptr.getErr(), PktErr::PKT_TOO_SHORT_FOR_L4_HEADER);
|
||||
}
|
||||
|
||||
TEST(Packet, icmp)
|
||||
{
|
||||
::Environment env;
|
||||
ConfigComponent config_comp;
|
||||
// correct ICMPV4 packet
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 "
|
||||
"0010: 00 1c 12 34 40 00 ff 01 6b aa 7f 00 00 01 7f 00 "
|
||||
"0020: 00 01 00 00 ff fd 00 01 00 01 00 00 00 00 00 00 "
|
||||
"0030: 00 00 00 00 00 00 00 00 00 00 00 00 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
ASSERT_TRUE(ptr.ok());
|
||||
EXPECT_EQ(ptr->get()->getKey().getProto(), IPPROTO_ICMP);
|
||||
EXPECT_EQ(ptr->get()->getPacketProto(), IPType::V4);
|
||||
auto p = ptr.unpackMove();
|
||||
auto icmp = p->getL4Header().getTypePtr<struct icmphdr>(0).unpack();
|
||||
auto checksum = ntohs(icmp->checksum);
|
||||
EXPECT_EQ(icmp->type, ICMP_ECHOREPLY);
|
||||
EXPECT_EQ(icmp->code, 0);
|
||||
EXPECT_EQ(checksum, 0xfffd);
|
||||
}
|
||||
|
||||
TEST(Packet, no_room_for_icmpv6_header)
|
||||
{
|
||||
// only 7 bytes of ICMPV6 (min is 8)
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 00 00 00 00 00 00 00 00 00 00 00 86 dd 60 00 "
|
||||
"0010: 00 00 00 07 3a ff 00 00 00 00 00 00 00 00 00 00 "
|
||||
"0020: 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 "
|
||||
"0030: 00 00 00 00 00 01 80 00 7f bc 00 00 00 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V6, v);
|
||||
ASSERT_FALSE(ptr.ok());
|
||||
EXPECT_EQ(ptr.getErr(), PktErr::PKT_TOO_SHORT_FOR_L4_HEADER);
|
||||
}
|
||||
|
||||
TEST(Packet, icmpv6)
|
||||
{
|
||||
::Environment env;
|
||||
ConfigComponent config_comp;
|
||||
// correct ICMPV6 packet
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 00 00 00 00 00 00 00 00 00 00 00 86 dd 60 00 "
|
||||
"0010: 00 00 00 0c 3a ff 00 00 00 00 00 00 00 00 00 00 "
|
||||
"0020: 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 "
|
||||
"0030: 00 00 00 00 00 01 80 00 3b 51 00 00 00 00 11 22 "
|
||||
"0040: 33 44 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V6, v);
|
||||
ASSERT_TRUE(ptr.ok());
|
||||
EXPECT_EQ(ptr->get()->getKey().getProto(), IPPROTO_ICMPV6);
|
||||
EXPECT_EQ(ptr->get()->getPacketProto(), IPType::V6);
|
||||
auto p = ptr.unpackMove();
|
||||
auto icmp = p->getL4Header().getTypePtr<struct icmp6_hdr>(0).unpack();
|
||||
auto checksum = ntohs(icmp->icmp6_cksum);
|
||||
EXPECT_EQ(icmp->icmp6_type, ICMP6_ECHO_REQUEST);
|
||||
EXPECT_EQ(icmp->icmp6_code, 0);
|
||||
EXPECT_EQ(checksum, 0x3b51);
|
||||
}
|
||||
|
||||
TEST(Packet, icmp_over_ipv6)
|
||||
{
|
||||
// correct ICMPV4 packet over IPV6
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 00 00 00 00 00 00 00 00 00 00 00 86 dd 60 00 "
|
||||
"0010: 00 00 00 0c 01 ff 00 00 00 00 00 00 00 00 00 00 "
|
||||
"0020: 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 "
|
||||
"0030: 00 00 00 00 00 01 00 00 ff fd 00 01 00 01 00 00 "
|
||||
"0040: 00 00 00 00 00 00 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V6, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::ICMP_VERSION_MISMATCH));
|
||||
}
|
||||
|
||||
TEST(Packet, icmpv6_over_ipv4)
|
||||
{
|
||||
// correct ICMPV6 packet over IPV4
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 "
|
||||
"0010: 00 1c 12 34 40 00 ff 3a 6b aa 7f 00 00 01 7f 00 "
|
||||
"0020: 00 01 80 00 3b 51 00 00 00 00 11 22 33 44 00 00 "
|
||||
"0030: 00 00 00 00 00 00 00 00 00 00 00 00 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
EXPECT_THAT(ptr, IsError(PktErr::ICMP_VERSION_MISMATCH));
|
||||
}
|
||||
|
||||
TEST(Packet, tcp_fragment_noheader)
|
||||
{
|
||||
// IPv4 TCP fragmented packet with no TCP header
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 "
|
||||
"0010: 00 28 12 34 00 5d ff 06 00 00 7f 00 00 01 7f 00 "
|
||||
"0020: 00 01 00 00 00 50 00 00 00 64 00 00 00 64 50 00 "
|
||||
"0030: 0f a0 a1 2a 00 00 00 00 00 00 00 00 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
ConnKey key(
|
||||
IPAddr::createIPAddr("127.0.0.1").unpack(), 0,
|
||||
IPAddr::createIPAddr("127.0.0.1").unpack(), 0,
|
||||
6
|
||||
);
|
||||
EXPECT_EQ(key, ptr.unpack()->getKey());
|
||||
}
|
||||
|
||||
TEST(Packet, tcp_notfragment)
|
||||
{
|
||||
// IPv4 fragmented packet with TCP header
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 "
|
||||
"0010: 00 28 12 34 20 00 ff 06 00 00 7f 00 00 01 7f 00 "
|
||||
"0020: 00 01 00 00 00 50 00 00 00 64 00 00 00 64 50 00 "
|
||||
"0030: 0f a0 a1 2a 00 00 00 00 00 00 00 00 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
ConnKey key(
|
||||
IPAddr::createIPAddr("127.0.0.1").unpack(), 0,
|
||||
IPAddr::createIPAddr("127.0.0.1").unpack(), 0,
|
||||
6
|
||||
);
|
||||
EXPECT_EQ(key, ptr.unpack()->getKey());
|
||||
}
|
||||
|
||||
TEST(Packet, ipv6_fragment_noheader)
|
||||
{
|
||||
// IPv6 fragmented packet with no L4 header
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 1d 09 94 65 38 68 5b 35 c0 61 b6 86 dd 60 02 "
|
||||
"0010: 12 89 00 1a 2c 40 26 07 f0 10 03 f9 00 00 00 00 "
|
||||
"0020: 00 00 00 00 10 01 26 07 f0 10 03 f9 00 00 00 00 "
|
||||
"0030: 00 00 00 11 00 00 11 00 05 a9 f8 8e b4 66 68 68 "
|
||||
"0040: 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 "
|
||||
"0050: 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V4, v);
|
||||
ConnKey key(
|
||||
IPAddr::createIPAddr("2607:f010:3f9::1001").unpack(), 0,
|
||||
IPAddr::createIPAddr("2607:f010:3f9::11:0").unpack(), 0,
|
||||
17
|
||||
);
|
||||
EXPECT_EQ(key, ptr.unpack()->getKey());
|
||||
}
|
||||
|
||||
TEST(Packet, ipv6_fragment_with_header)
|
||||
{
|
||||
// IPv6 fragmented packet with L4 header
|
||||
auto v = cptestParseHex(
|
||||
"0000: 00 1d 09 94 65 38 68 5b 35 c0 61 b6 86 dd 60 02 "
|
||||
"0010: 12 89 00 1a 2c 40 26 07 f0 10 03 f9 00 00 00 00 "
|
||||
"0020: 00 00 00 00 10 01 26 07 f0 10 03 f9 00 00 00 00 "
|
||||
"0030: 00 00 00 11 00 00 11 00 00 01 f8 8e b4 66 18 db "
|
||||
"0040: 18 db 15 0b 79 16 06 fd 14 ff 07 29 08 07 65 78 "
|
||||
"0050: 61 6d 70 6c 65 08 07 74 65 73 74 41 70 70 08 01 "
|
||||
);
|
||||
auto ptr = Packet::genPacket(PktType::PKT_L2, IPType::V6, v);
|
||||
ConnKey key(
|
||||
IPAddr::createIPAddr("2607:f010:3f9::1001").unpack(), 0,
|
||||
IPAddr::createIPAddr("2607:f010:3f9::11:0").unpack(), 0,
|
||||
17
|
||||
);
|
||||
EXPECT_EQ(key, ptr.unpack()->getKey());
|
||||
}
|
||||
|
||||
TEST(CDir, printout_operator)
|
||||
{
|
||||
stringstream buf_c2s;
|
||||
buf_c2s << CDir::C2S;
|
||||
EXPECT_EQ(buf_c2s.str(), "c2s");
|
||||
|
||||
stringstream buf_s2c;
|
||||
buf_s2c << CDir::S2C;
|
||||
EXPECT_EQ(buf_s2c.str(), "s2c");
|
||||
}
|
Reference in New Issue
Block a user