TEST_F(PDUTest, OperatorConcatOnPacket) { std::string raw_payload = "Test"; Packet packet = IP("192.168.0.1") / TCP(22, 52); TCP *tcp = packet.pdu()->find_pdu<TCP>(); ASSERT_TRUE(tcp != NULL); tcp /= RawPDU(raw_payload); RawPDU *raw = packet.pdu()->find_pdu<RawPDU>(); ASSERT_TRUE(raw != NULL); ASSERT_EQ(raw->payload_size(), raw_payload.size()); EXPECT_TRUE(std::equal(raw->payload().begin(), raw->payload().end(), raw_payload.begin())); }
TEST_F(PDUTest, OperatorConcat) { std::string raw_payload = "Test"; IP ip = IP("192.168.0.1") / TCP(22, 52) / RawPDU(raw_payload); EXPECT_EQ(ip.dst_addr(), "192.168.0.1"); ASSERT_TRUE(ip.inner_pdu() != NULL); TCP *tcp = ip.find_pdu<TCP>(); ASSERT_TRUE(tcp != NULL); EXPECT_EQ(tcp->dport(), 22); EXPECT_EQ(tcp->sport(), 52); ASSERT_TRUE(tcp->inner_pdu() != NULL); RawPDU *raw = tcp->find_pdu<RawPDU>(); ASSERT_TRUE(raw != NULL); ASSERT_EQ(raw->payload_size(), raw_payload.size()); EXPECT_TRUE(std::equal(raw_payload.begin(), raw_payload.end(), raw->payload().begin())); }
void IPv4ReassemblerTest::test_packets(const std::vector<std::pair<const uint8_t*, size_t> > &vt) { IPv4Reassembler reassembler; for(size_t i = 0; i < vt.size(); ++i) { EthernetII eth(vt[i].first, (uint32_t)vt[i].second); IPv4Reassembler::packet_status status = reassembler.process(eth); EXPECT_NE(IPv4Reassembler::NOT_FRAGMENTED, status); if(status == IPv4Reassembler::REASSEMBLED) { ASSERT_EQ(static_cast<size_t>(vt.size() - 1), i); ASSERT_TRUE(eth.find_pdu<UDP>() != NULL); RawPDU *raw = eth.find_pdu<RawPDU>(); ASSERT_TRUE(raw != NULL); ASSERT_EQ(15000ULL, raw->payload().size()); } else if(status == IPv4Reassembler::FRAGMENTED) EXPECT_NE(vt.size() - 1, i); } }
bool TCPStream::generic_process(uint32_t& my_seq, uint32_t& /*other_seq*/, payload_type& pload, fragments_type& frags, TCP* tcp) { bool added_some(false); if (tcp->get_flag(TCP::FIN) || tcp->get_flag(TCP::RST)) { fin_sent_ = true; } RawPDU* raw = static_cast<RawPDU*>(tcp->release_inner_pdu()); if (raw) { const uint32_t chunk_end = add_sequence_numbers(tcp->seq(), raw->payload_size()); // If the end of the chunk ends after our current sequence number, process it. if (compare_seq_numbers(chunk_end, my_seq) >= 0) { uint32_t seq = tcp->seq(); // If it starts before our sequence number, slice it if (compare_seq_numbers(seq, my_seq) < 0) { const uint32_t diff = subtract_sequence_numbers(my_seq, seq); raw->payload().erase( raw->payload().begin(), raw->payload().begin() + diff ); seq = my_seq; } safe_insert(frags, seq, raw); fragments_type::iterator it = frags.find(my_seq); // Keep looping while the fragments seq is lower or equal to our seq while (it != frags.end() && compare_seq_numbers(it->first, my_seq) <= 0) { // Does this fragment start before our sequence number? if (compare_seq_numbers(it->first, my_seq) < 0) { uint32_t fragment_end = add_sequence_numbers(it->first, it->second->payload_size()); int comparison = compare_seq_numbers(fragment_end, my_seq); // Does it end after our sequence number? if (comparison > 0) { // Then slice it RawPDU::payload_type& payload = it->second->payload(); payload.erase( payload.begin(), payload.begin() + subtract_sequence_numbers(my_seq, it->first) ); safe_insert(frags, my_seq, it->second); it = erase_iterator(it, frags); } else { // Otherwise, we've seen this part of the payload. Erase it. delete it->second; it = erase_iterator(it, frags); } } else { // They're equal. Add this payload. pload.insert( pload.end(), it->second->payload().begin(), it->second->payload().end() ); my_seq += it->second->payload_size(); delete it->second; it = erase_iterator(it, frags); added_some = true; if (frags.empty()) { break; } } } } else { delete raw; } } return added_some; }
static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) { Mode mode = ((nf_data*)data)->mode; u_int32_t id = ntohl(nfq_get_msg_packet_hdr(nfa)->packet_id); unsigned char *packet; int size = nfq_get_payload(nfa, &packet); std::vector<uint8_t> result; u_int32_t verdict = NF_ACCEPT; try { IP ip = IP(packet, size); //cout << ip.src_addr() << " -> " << ip.dst_addr() << endl; NetworkInterface interface(ip.dst_addr()); IP::address_type interface_addr = interface.addresses().ip_addr; RR *rr = ip.find_pdu<RR>(); if (mode == ROUTER) { if (rr != 0) { //cout << "Adding to existing RR" << endl; } else { create_rr(ip); rr = ip.find_pdu<RR>(); if (is_spoof && ip.src_addr() == IP::address_type("192.168.30.10")) { rr->route().push_back(RREntry(IP::address_type("192.168.100.20"), 42, 42)); } } // TODO Figure out what the magic numbers are for the source address RREntry src_hop(ip.src_addr(), 0x0, 0x0); RREntry last_hop = src_hop; if (rr != 0 && rr->route().size() >= 1) last_hop = rr->route().back(); AITF_packet aitf; if (should_intercept(ip, rr, &aitf)) { //cout << "Intercepting packet" << endl; send_AITF_message(aitf, IP::address_type("192.168.10.100")); verdict = NF_DROP; } else if (is_blocked(last_hop, ip.dst_addr()) || (is_shadow && rr->route().size() > 1 && is_blocked(src_hop, ip.dst_addr()))) { //cout << "Packet blocked" << endl; verdict = NF_DROP; } else if (hosts.isLegacyHost(ip.dst_addr())) { //cout << "Legacy host detected" << endl; if (rr != 0) { //print_route(rr->route()); strip_rr(ip, *rr); } else { //cout << "No RR table present" << endl; } } else { NetworkInterface interface(ip.dst_addr()); rr->route().push_back(RREntry(interface_addr, hash_for_destination(ip.dst_addr(), 0), hash_for_destination(ip.dst_addr(), 1))); if (rr->route().size() > rr->route_capacity()) { //cout << "RR table filled. Dropping packet." << endl; verdict = NF_DROP; } //else print_route(rr->route()); } } else if (mode == HOST) { if (rr != 0) { // Check if this is a bad packet // TODO don't hard code attacker ip addresses bool is_bad = false; try { UDP udp(&rr->payload()[0], rr->payload().size()); RawPDU* raw = udp.find_pdu<RawPDU>(); if (raw != 0) { is_bad = raw->payload()[0] == 1; } } catch (malformed_packet e) { } if (is_bad && is_victim) { if (!last_event_set) { printf("Attack detected\n"); gettimeofday(&last_event, NULL); last_event_set = true; event_delay = 500000; } else { struct timeval now; gettimeofday(&now, NULL); if ((now.tv_sec - last_event.tv_sec) * 1000000 + now.tv_usec - last_event.tv_usec > event_delay) { printf("Enforce sent\n"); print_route(rr->route()); vector<RRFilter> filters; filters.push_back(RRFilter(is_wildcard ? 1 : 0, ip.src_addr(), 0x0, 0x0)); for (int i = 0; i < rr->route().size(); i++) { const RREntry& entry = rr->route().at(i); filters.push_back(RRFilter(is_wildcard ? 1 : 0, entry.address(), entry.random_number_1(), entry.random_number_2())); } AITF_packet enforce(0, 0, 0, 1, filters, IP::address_type("192.168.10.10"), filters.size()); send_AITF_message(enforce, IP::address_type("192.168.10.100")); last_event = now; event_delay = is_aggressive ? 1000000 : 10000000; } } } //print_route(rr->route()); strip_rr(ip, *rr); } else { //cout << "No RR table present" << endl; } } result = ip.serialize(); //cout << endl; } catch (malformed_packet e) { cout << "malformed packet " << e.what() << endl; } return nfq_set_verdict(qh, id, verdict, verdict == NF_DROP ? 0 : result.size(), verdict == NF_DROP ? 0 : &result[0]); }