#include #include #include #include #include #include #include #include #include #include using namespace vanetza; using namespace vanetza::geonet; class RouterRequest : public ::testing::Test { public: RouterRequest() : security(runtime), router(runtime, mib) {} protected: virtual void SetUp() override { mib.itsGnSecurity = true; router.set_access_interface(&req_ifc); router.set_security_entity(&security.entity()); router.set_transport_handler(geonet::UpperProtocol::IPv6, &ind_ifc); test_payload[OsiLayer::Application] = ByteBuffer {47, 11, 1, 4, 42, 85}; } std::unique_ptr create_packet() { std::unique_ptr packet { new DownPacket(test_payload) }; return packet; } ManagementInformationBase mib; ManualRuntime runtime; SecurityContext security; Router router; FakeRequestInterface req_ifc; FakeTransportInterface ind_ifc; ChunkPacket test_payload; }; TEST_F(RouterRequest, router_request) { // create ShbDataRequest ShbDataRequest request(mib, aid::CA); request.upper_protocol = UpperProtocol::IPv6; // Router handles request auto confirm = router.request(request, create_packet()); EXPECT_TRUE(confirm.accepted()); // get the data from the fake network ByteBuffer net_payload; for (const auto layer : osi_layer_range()) { ByteBuffer tmp; req_ifc.m_last_packet->layer(layer).convert(tmp); std::copy(tmp.begin(), tmp.end(), std::back_inserter(net_payload)); } UpPacket packet_up { CohesivePacket(net_payload, OsiLayer::Network) }; DownPacket packet_mac = *req_ifc.m_last_packet; // all data should be in network layer: payload is encapsulated by secured message EXPECT_EQ(packet_mac.size(), packet_mac[OsiLayer::Network].size()); // prepare access to network layer's PDU using pdu_convertible = convertible::byte_buffer_impl>; pdu_convertible* pdu_conv = dynamic_cast(packet_mac[OsiLayer::Network].ptr()); ASSERT_TRUE(pdu_conv); auto pdu = pdu_conv->m_pdu.get(); ASSERT_TRUE(pdu); auto pdu_ext = dynamic_cast(pdu); ASSERT_TRUE(pdu_ext); // check if packet has secured part EXPECT_EQ(NextHeaderBasic::Secured, pdu->basic().next_header); EXPECT_TRUE(pdu_ext->secured()); auto secured = *pdu_ext->secured(); // check payload of packet auto secured2 = boost::get(&secured); ASSERT_TRUE(secured2); EXPECT_EQ(security::v2::PayloadType::Signed, secured2->payload.type); EXPECT_EQ(test_payload.size(), pdu->common().payload); const size_t payload_header_length = CommonHeader::length_bytes + ShbHeader::length_bytes; EXPECT_EQ(payload_header_length, size(secured2->payload.data, OsiLayer::Network)); EXPECT_EQ(test_payload.size(), size(secured2->payload.data, OsiLayer::Transport, OsiLayer::Application)); ChunkPacket sec_payload = boost::get(secured2->payload.data); ChunkPacket sec_header = sec_payload.extract(OsiLayer::Network, OsiLayer::Network); ByteBuffer actual_payload, expected_payload; serialize_into_buffer(sec_payload, actual_payload); serialize_into_buffer(test_payload, expected_payload); EXPECT_EQ(expected_payload, actual_payload); ByteBuffer actual_payload_header, expected_payload_header; geonet::serialize_into_buffer(pdu_ext->common(), expected_payload_header); geonet::serialize_into_buffer(pdu_ext->extended(), expected_payload_header); sec_header[OsiLayer::Network].convert(actual_payload_header); EXPECT_EQ(expected_payload_header, actual_payload_header); } TEST_F(RouterRequest, modified_request_maximum_lifetime) { // create ShbDataRequest ShbDataRequest request(mib, aid::CA); // create new Lifetime that is larger than the itsGnMaxPacketLifetime of mib Lifetime large_lifetime(Lifetime::Base::Hundred_Seconds, 9); request.maximum_lifetime = large_lifetime; request.upper_protocol = UpperProtocol::IPv6; // Router handles request auto confirm = router.request(request, create_packet()); EXPECT_EQ(DataConfirm::ResultCode::Rejected_Max_Lifetime, confirm.result_code); } TEST_F(RouterRequest, modified_request_repetition) { // create ShbDataRequest ShbDataRequest request(mib, aid::CA); // create durations that will fail in data_confirm auto rep_faulty_int = 0.0 * units::si::seconds; // this has to be lower than mib.itsGnMinPacketRepetitionInterval auto rep_max = 99.0 * units::si::seconds; // create Repetition with faulty interval DataRequest::Repetition rep; rep.interval = rep_faulty_int; rep.maximum = rep_max; request.repetition = rep; request.upper_protocol = UpperProtocol::IPv6; // Router handles request auto confirm = router.request(request, create_packet()); EXPECT_EQ(DataConfirm::ResultCode::Rejected_Min_Repetition_Interval, confirm.result_code); } TEST_F(RouterRequest, modified_request_payload_null) { // create ShbDataRequest ShbDataRequest request(mib, aid::CA); request.upper_protocol = UpperProtocol::IPv6; // Router handles request auto confirm = router.request(request, nullptr); EXPECT_EQ(DataConfirm::ResultCode::Rejected_Unspecified, confirm.result_code); } TEST_F(RouterRequest, modified_request_large_payload) { std::unique_ptr packet { new geonet::DownPacket() }; // create too large payload ByteBuffer payload_large; for (int i = 0; i < 1000; i++) { ByteBuffer tmp = {0,1,2,3,4,5,6,7,8,9}; payload_large.insert(payload_large.end(), tmp.begin(), tmp.end()); } // insert payload in packet packet->layer(OsiLayer::Transport) = ByteBuffer(payload_large); // create ShbDataRequest ShbDataRequest request(mib, aid::CA); request.upper_protocol = UpperProtocol::IPv6; // Router handles request auto confirm = router.request(request, std::move(packet)); EXPECT_EQ(DataConfirm::ResultCode::Rejected_Max_SDU_Size, confirm.result_code); } TEST_F(RouterRequest, shb_repetition) { ShbDataRequest request(mib, aid::CA); request.repetition = DataRequest::Repetition { 0.1 * units::si::seconds, 10.0 * units::si::seconds }; EXPECT_EQ(0, req_ifc.m_requests); auto confirm = router.request(request, create_packet()); EXPECT_EQ(DataConfirm::ResultCode::Accepted, confirm.result_code); EXPECT_EQ(1, req_ifc.m_requests); ASSERT_TRUE(!!req_ifc.m_last_packet); // length of network layer is excluded because of varying secured message header fields const auto payload_size = size(*req_ifc.m_last_packet, OsiLayer::Transport, OsiLayer::Application); // trigger five repetitions for (unsigned i = 0; i < 5; ++i) { runtime.trigger(std::chrono::milliseconds(100)); } EXPECT_EQ(6, req_ifc.m_requests); EXPECT_EQ(payload_size, size(*req_ifc.m_last_packet, OsiLayer::Transport, OsiLayer::Application)); }