use super::*;
use proptest::*;
use proptest::prelude::*;
pub fn error_field_any() -> impl Strategy<Value = ErrorField> {
use ErrorField::*;
prop_oneof![
Just(Ipv4PayloadLength),
Just(Ipv4Dscp),
Just(Ipv4Ecn),
Just(Ipv4FragmentsOffset),
Just(Ipv6FlowLabel),
Just(VlanTagPriorityCodePoint),
Just(VlanTagVlanId)
]
}
pub fn vlan_ethertype_any() -> impl Strategy<Value = u16> {
prop_oneof![
Just(ether_type::VLAN_TAGGED_FRAME),
Just(ether_type::PROVIDER_BRIDGING),
Just(ether_type::VLAN_DOUBLE_TAGGED_FRAME),
]
}
prop_compose! {
pub(crate) fn ethernet_2_with(ether_type: u16)(
source in prop::array::uniform6(any::<u8>()),
dest in prop::array::uniform6(any::<u8>()),
ether_type in proptest::strategy::Just(ether_type))
-> Ethernet2Header
{
Ethernet2Header {
source: source,
destination: dest,
ether_type: ether_type
}
}
}
prop_compose! {
pub(crate) fn ethernet_2_any()
(ether_type in any::<u16>())
(result in ethernet_2_with(ether_type))
-> Ethernet2Header
{
result
}
}
pub static ETHERNET_KNOWN_ETHER_TYPES: &'static [u16] = &[
EtherType::Ipv4 as u16,
EtherType::Ipv6 as u16,
EtherType::VlanTaggedFrame as u16,
EtherType::ProviderBridging as u16,
EtherType::VlanDoubleTaggedFrame as u16
];
prop_compose! {
pub(crate) fn ethernet_2_unknown()(
source in prop::array::uniform6(any::<u8>()),
dest in prop::array::uniform6(any::<u8>()),
ether_type in any::<u16>().prop_filter("ether_type must be unknown",
|v| !ETHERNET_KNOWN_ETHER_TYPES.iter().any(|&x| v == &x)))
-> Ethernet2Header
{
Ethernet2Header {
source: source,
destination: dest,
ether_type: ether_type
}
}
}
prop_compose! {
pub(crate) fn vlan_single_unknown()(
priority_code_point in prop::bits::u8::between(0,3),
drop_eligible_indicator in any::<bool>(),
vlan_identifier in prop::bits::u16::between(0,12),
ether_type in any::<u16>().prop_filter("ether_type must be unknown",
|v| !ETHERNET_KNOWN_ETHER_TYPES.iter().any(|&x| v == &x)))
-> SingleVlanHeader
{
SingleVlanHeader {
priority_code_point: priority_code_point,
drop_eligible_indicator: drop_eligible_indicator,
vlan_identifier: vlan_identifier,
ether_type: ether_type
}
}
}
prop_compose! {
pub(crate) fn vlan_single_with(ether_type: u16)(
priority_code_point in prop::bits::u8::between(0,3),
drop_eligible_indicator in any::<bool>(),
vlan_identifier in prop::bits::u16::between(0,12),
ether_type in proptest::strategy::Just(ether_type))
-> SingleVlanHeader
{
SingleVlanHeader {
priority_code_point: priority_code_point,
drop_eligible_indicator: drop_eligible_indicator,
vlan_identifier: vlan_identifier,
ether_type: ether_type
}
}
}
prop_compose! {
pub(crate) fn vlan_single_any()
(ether_type in any::<u16>())
(result in vlan_single_with(ether_type))
-> SingleVlanHeader
{
result
}
}
prop_compose! {
pub(crate) fn vlan_double_any()
(ether_type in any::<u16>())
(result in vlan_double_with(ether_type))
-> DoubleVlanHeader
{
result
}
}
prop_compose! {
pub(crate) fn vlan_double_with(ether_type: u16)(
outer_ethertype in vlan_ethertype_any(),
inner_ethertype in proptest::strategy::Just(ether_type)
)(
outer in vlan_single_with(outer_ethertype),
inner in vlan_single_with(inner_ethertype)
) -> DoubleVlanHeader {
DoubleVlanHeader {
outer,
inner
}
}
}
prop_compose! {
pub(crate) fn ipv4_with(protocol: u8)
(
ihl in 0u8..10,
protocol in proptest::strategy::Just(protocol))
(source in prop::array::uniform4(any::<u8>()),
dest in prop::array::uniform4(any::<u8>()),
dscp in prop::bits::u8::between(0,6),
ecn in prop::bits::u8::between(0,2),
identification in any::<u16>(),
ttl in any::<u8>(),
dont_fragment in any::<bool>(),
more_fragments in any::<bool>(),
fragments_offset in prop::bits::u16::between(0, 13),
header_checksum in any::<u16>(),
payload_len in 0..(std::u16::MAX - u16::from(ihl*4) - (Ipv4Header::SERIALIZED_SIZE as u16)),
protocol in proptest::strategy::Just(protocol),
options_len in proptest::strategy::Just(ihl*4),
options_part0 in prop::array::uniform32(any::<u8>()),
options_part1 in prop::array::uniform8(any::<u8>())
) -> Ipv4Header
{
let mut result: Ipv4Header = Default::default();
{
let mut options: [u8;40] = [0;40];
let len = usize::from(options_len);
if len > 0 {
let sub_len = std::cmp::min(len,32);
options[..sub_len].copy_from_slice(&options_part0[..sub_len]);
}
if len > 32 {
let sub_len = len - 32;
options[32..len].copy_from_slice(&options_part1[..sub_len]);
}
result.set_options(&options[..len]).unwrap();
}
result.differentiated_services_code_point = dscp;
result.explicit_congestion_notification = ecn;
result.payload_len = payload_len;
result.identification = identification;
result.dont_fragment = dont_fragment;
result.more_fragments = more_fragments;
result.fragments_offset = fragments_offset;
result.time_to_live = ttl;
result.protocol = protocol;
result.header_checksum = header_checksum;
result.source = source;
result.destination = dest;
return result;
}
}
prop_compose! {
pub(crate) fn ipv4_any()
(protocol in any::<u8>())
(result in ipv4_with(protocol))
-> Ipv4Header
{
result
}
}
static IPV4_KNOWN_PROTOCOLS: &'static [u8] = &[
ip_number::UDP,
ip_number::TCP,
ip_number::AUTH,
];
prop_compose! {
pub(crate) fn ipv4_unknown()
(protocol in any::<u8>().prop_filter("protocol must be unknown",
|v| !IPV4_KNOWN_PROTOCOLS.iter().any(|&x| v == &x))
)
(header in ipv4_with(protocol)
) -> Ipv4Header
{
header
}
}
prop_compose! {
pub(crate) fn ipv4_extensions_with(next_header: u8)
(
has_auth in any::<bool>(),
auth in ip_authentication_with(next_header)
) -> Ipv4Extensions
{
if has_auth {
Ipv4Extensions{
auth: Some(auth),
}
} else {
Ipv4Extensions{
auth: None,
}
}
}
}
prop_compose! {
pub(crate) fn ipv4_extensions_any()
(protocol in any::<u8>())
(result in ipv4_extensions_with(protocol))
-> Ipv4Extensions
{
result
}
}
prop_compose! {
pub(crate) fn ipv4_extensions_unknown()
(
next_header in any::<u8>().prop_filter(
"next_header must be unknown",
|v| !IPV4_KNOWN_PROTOCOLS.iter().any(|&x| v == &x)
)
) (
result in ipv4_extensions_with(next_header)
) -> Ipv4Extensions
{
result
}
}
prop_compose! {
pub(crate) fn ipv6_with(next_header: u8)
(
source in prop::array::uniform16(any::<u8>()),
dest in prop::array::uniform16(any::<u8>()),
traffic_class in any::<u8>(),
flow_label in prop::bits::u32::between(0,20),
payload_length in any::<u16>(),
hop_limit in any::<u8>(),
next_header in proptest::strategy::Just(next_header)
) -> Ipv6Header
{
Ipv6Header {
traffic_class: traffic_class,
flow_label: flow_label,
payload_length: payload_length,
next_header: next_header,
hop_limit: hop_limit,
source: source,
destination: dest
}
}
}
prop_compose! {
pub(crate) fn ipv6_any()
(next_header in any::<u8>())
(result in ipv6_with(next_header)
) -> Ipv6Header
{
result
}
}
static IPV6_KNOWN_NEXT_HEADERS: &'static [u8] = &[
ip_number::UDP,
ip_number::TCP,
ip_number::IPV6_HOP_BY_HOP,
ip_number::IPV6_ROUTE,
ip_number::IPV6_FRAG,
ip_number::AUTH,
ip_number::IPV6_DEST_OPTIONS,
ip_number::MOBILITY,
ip_number::HIP,
ip_number::SHIM6,
];
prop_compose! {
pub(crate) fn ipv6_unknown()(
source in prop::array::uniform16(any::<u8>()),
dest in prop::array::uniform16(any::<u8>()),
traffic_class in any::<u8>(),
flow_label in prop::bits::u32::between(0,20),
payload_length in any::<u16>(),
hop_limit in any::<u8>(),
next_header in any::<u8>().prop_filter("next_header must be unknown",
|v| !IPV6_KNOWN_NEXT_HEADERS.iter().any(|&x| v == &x))
) -> Ipv6Header
{
Ipv6Header {
traffic_class: traffic_class,
flow_label: flow_label,
payload_length: payload_length,
next_header: next_header,
hop_limit: hop_limit,
source: source,
destination: dest
}
}
}
prop_compose! {
pub(crate) fn ipv6_raw_extension_with(
next_header: u8,
len: u8
) (
next_header in proptest::strategy::Just(next_header),
payload in proptest::collection::vec(any::<u8>(), (len as usize)*8 + 6)
) -> Ipv6RawExtensionHeader
{
Ipv6RawExtensionHeader::new_raw(
next_header,
&payload[..]
).unwrap()
}
}
prop_compose! {
pub(crate) fn ipv6_raw_extension_any()
(
next_header in any::<u8>(),
len in any::<u8>()
) (
result in ipv6_raw_extension_with(next_header, len)
) -> Ipv6RawExtensionHeader
{
result
}
}
prop_compose! {
pub(crate) fn ipv6_extensions_with(next_header: u8)
(
has_hop_by_hop_options in any::<bool>(),
hop_by_hop_options in ipv6_raw_extension_any(),
has_destination_options in any::<bool>(),
destination_options in ipv6_raw_extension_any(),
has_routing in any::<bool>(),
routing in ipv6_raw_extension_any(),
has_fragment in any::<bool>(),
fragment in ipv6_fragment_any(),
has_auth in any::<bool>(),
auth in ip_authentication_with(next_header),
has_final_destination_options in any::<bool>(),
final_destination_options in ipv6_raw_extension_any()
) -> Ipv6Extensions
{
let mut result = Ipv6Extensions {
hop_by_hop_options: if has_hop_by_hop_options {
Some(hop_by_hop_options)
} else {
None
},
destination_options: if has_destination_options {
Some(destination_options)
} else {
None
},
routing: if has_routing {
Some(
Ipv6RoutingExtensions{
routing,
final_destination_options: if has_final_destination_options {
Some(final_destination_options)
} else {
None
}
}
)
} else {
None
},
fragment: if has_fragment {
Some(fragment)
} else {
None
},
auth: if has_auth {
Some(auth)
} else {
None
},
};
result.set_next_headers(next_header);
result
}
}
prop_compose! {
pub(crate) fn ipv6_extensions_any()
(
next_header in any::<u8>()
) (
result in ipv6_extensions_with(next_header)
) -> Ipv6Extensions
{
result
}
}
prop_compose! {
pub(crate) fn ipv6_extensions_unknown()
(
next_header in any::<u8>().prop_filter(
"next_header must be unknown",
|v| !IPV6_KNOWN_NEXT_HEADERS.iter().any(|&x| v == &x)
)
) (
result in ipv6_extensions_with(next_header)
) -> Ipv6Extensions
{
result
}
}
prop_compose! {
pub(crate) fn ipv6_fragment_with(
next_header: u8
) (
next_header in proptest::strategy::Just(next_header),
fragment_offset in 0u16..=0b0001_1111_1111_1111u16,
more_fragments in any::<bool>(),
identification in any::<u32>(),
) -> Ipv6FragmentHeader
{
Ipv6FragmentHeader::new(
next_header,
fragment_offset,
more_fragments,
identification
)
}
}
prop_compose! {
pub(crate) fn ipv6_fragment_any()
(next_header in any::<u8>())
(result in ipv6_fragment_with(next_header)
) -> Ipv6FragmentHeader
{
result
}
}
prop_compose! {
pub(crate) fn ip_authentication_with(
next_header: u8
) (
next_header in proptest::strategy::Just(next_header),
len in 1..0xffu8
) (
next_header in proptest::strategy::Just(next_header),
spi in any::<u32>(),
sequence_number in any::<u32>(),
icv in proptest::collection::vec(any::<u8>(), (len as usize)*4)
) -> IpAuthenticationHeader {
IpAuthenticationHeader::new(
next_header,
spi,
sequence_number,
&icv
).unwrap()
}
}
prop_compose! {
pub(crate) fn ip_authentication_any() (
next_header in any::<u8>()
) (
header in ip_authentication_with(next_header)
) -> IpAuthenticationHeader {
header
}
}
prop_compose! {
pub(crate) fn udp_any()(
source_port in any::<u16>(),
destination_port in any::<u16>(),
length in any::<u16>(),
checksum in any::<u16>())
-> UdpHeader
{
UdpHeader {
source_port: source_port,
destination_port: destination_port,
length: length,
checksum: checksum
}
}
}
prop_compose! {
pub(crate) fn tcp_any()
(data_offset in TCP_MINIMUM_DATA_OFFSET..(TCP_MAXIMUM_DATA_OFFSET + 1))
(
source_port in any::<u16>(),
destination_port in any::<u16>(),
sequence_number in any::<u32>(),
acknowledgment_number in any::<u32>(),
ns in any::<bool>(),
fin in any::<bool>(),
syn in any::<bool>(),
rst in any::<bool>(),
psh in any::<bool>(),
ack in any::<bool>(),
ece in any::<bool>(),
urg in any::<bool>(),
cwr in any::<bool>(),
window_size in any::<u16>(),
checksum in any::<u16>(),
urgent_pointer in any::<u16>(),
options in proptest::collection::vec(any::<u8>(), ((data_offset - 5) as usize)*4))
-> TcpHeader
{
let mut result = TcpHeader::new(source_port, destination_port, sequence_number, window_size);
result.acknowledgment_number = acknowledgment_number;
result.ns = ns;
result.fin = fin;
result.syn = syn;
result.rst = rst;
result.psh = psh;
result.ack = ack;
result.ece = ece;
result.urg = urg;
result.cwr = cwr;
result.checksum = checksum;
result.urgent_pointer = urgent_pointer;
result.set_options_raw(&options[..]).unwrap();
result
}
}
pub fn ip_number_any() -> impl Strategy<Value = IpNumber> {
use IpNumber::*;
prop_oneof![
Just(IPv6HeaderHopByHop),
Just(Icmp),
Just(Igmp),
Just(Ggp),
Just(IPv4),
Just(Stream),
Just(Tcp),
Just(Cbt),
Just(Egp),
Just(Igp),
Just(BbnRccMon),
Just(NvpII),
Just(Pup),
Just(Argus),
Just(Emcon),
Just(Xnet),
Just(Chaos),
Just(Udp),
Just(Mux),
Just(DcnMeas),
Just(Hmp),
Just(Prm),
Just(XnsIdp),
Just(Trunk1),
Just(Trunk2),
Just(Leaf1),
Just(Leaf2),
Just(Rdp),
Just(Irtp),
Just(IsoTp4),
Just(NetBlt),
Just(MfeNsp),
Just(MeritInp),
Just(Dccp),
Just(ThirdPartyConnectProtocol),
Just(Idpr),
Just(Xtp),
Just(Ddp),
Just(IdprCmtp),
Just(TpPlusPlus),
Just(Il),
Just(Ipv6),
Just(Sdrp),
Just(IPv6RouteHeader),
Just(IPv6FragmentationHeader),
Just(Idrp),
Just(Rsvp),
Just(Gre),
Just(Dsr),
Just(Bna),
Just(EncapsulatingSecurityPayload),
Just(AuthenticationHeader),
Just(Inlsp),
Just(Swipe),
Just(Narp),
Just(Mobile),
Just(Tlsp),
Just(Skip),
Just(IPv6Icmp),
Just(IPv6NoNextHeader),
Just(IPv6DestinationOptions),
Just(AnyHostInternalProtocol),
Just(Cftp),
Just(AnyLocalNetwork),
Just(SatExpak),
Just(Krytolan),
Just(Rvd),
Just(Ippc),
Just(AnyDistributedFileSystem),
Just(SatMon),
Just(Visa),
Just(Ipcv),
Just(Cpnx),
Just(Cphb),
Just(Wsn),
Just(Pvp),
Just(BrSatMon),
Just(SunNd),
Just(WbMon),
Just(WbExpak),
Just(IsoIp),
Just(Vmtp),
Just(SecureVmtp),
Just(Vines),
Just(TtpOrIptm),
Just(NsfnetIgp),
Just(Dgp),
Just(Tcf),
Just(Eigrp),
Just(Ospfigp),
Just(SpriteRpc),
Just(Larp),
Just(Mtp),
Just(Ax25),
Just(Ipip),
Just(Micp),
Just(SccSp),
Just(EtherIp),
Just(Encap),
Just(Gmtp),
Just(Ifmp),
Just(Pnni),
Just(Pim),
Just(Aris),
Just(Scps),
Just(Qnx),
Just(ActiveNetworks),
Just(IpComp),
Just(SitraNetworksProtocol),
Just(CompaqPeer),
Just(IpxInIp),
Just(Vrrp),
Just(Pgm),
Just(AnyZeroHopProtocol),
Just(Layer2TunnelingProtocol),
Just(Ddx),
Just(Iatp),
Just(Stp),
Just(Srp),
Just(Uti),
Just(SimpleMessageProtocol),
Just(Sm),
Just(Ptp),
Just(IsisOverIpv4),
Just(Fire),
Just(Crtp),
Just(Crudp),
Just(Sscopmce),
Just(Iplt),
Just(Sps),
Just(Pipe),
Just(Sctp),
Just(Fc),
Just(RsvpE2eIgnore),
Just(MobilityHeader),
Just(UdpLite),
Just(MplsInIp),
Just(Manet),
Just(Hip),
Just(Shim6),
Just(Wesp),
Just(Rohc),
Just(ExperimentalAndTesting0),
Just(ExperimentalAndTesting1)
]
}