/** * @file PacketInfoCreator.hpp * @author Tobias * @brief * @date 2021-06-16 */ #pragma once #include #include #include "Definitions.hpp" #include "PacketDissection/PacketInfo.hpp" #include "PacketDissection/PacketInfoIpv4.hpp" #include "PacketDissection/PacketInfoIpv4Icmp.hpp" #include "PacketDissection/PacketInfoIpv4Tcp.hpp" #include "PacketDissection/PacketInfoIpv4Udp.hpp" #define RTE_ETHER_ADDR_LEN 6 #define ETHER_TYPE_IPv4 0x0800 class PacketInfoCreator { public: /** * @brief Create a PacketInfo object for given mbuf * * @param mbuf dpdk abstraction for one packet * @return PacketInfo* */ inline static PacketInfo* create_pkt_info(rte_mbuf* mbuf) { struct rte_ether_hdr* eth_hdr; eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr*); uint16_t offset = (uint16_t)sizeof(struct rte_ether_hdr); /// from here on we know the l3 type if (rte_be_to_cpu_16(eth_hdr->ether_type) == ETHER_TYPE_IPv4) { struct rte_ipv4_hdr* ip4_hdr; ip4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr*, offset); uint8_t protocol_id = ip4_hdr->next_proto_id; if (protocol_id == 6) { // TCP // calculate point where TCP-header begins offset = offset + (ip4_hdr->version_ihl - 64) * 4; // map TCP-header on memory struct rte_tcp_hdr* tcp_hdr; tcp_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_tcp_hdr*, offset); // create PacketInfo PacketInfoIpv4Tcp* pkt_inf = new PacketInfoIpv4Tcp(mbuf, eth_hdr, ip4_hdr, tcp_hdr); return pkt_inf; } else if (protocol_id == 17) { // UDP offset = offset + (ip4_hdr->version_ihl - 64) * 4; struct rte_udp_hdr* udp_hdr; udp_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_udp_hdr*, offset); PacketInfoIpv4Udp* pkt_inf = new PacketInfoIpv4Udp(mbuf, eth_hdr, ip4_hdr, udp_hdr); return pkt_inf; } else if (protocol_id == 1) { // ICMP offset = offset + (ip4_hdr->version_ihl - 64) * 4; struct rte_icmp_hdr* icmp_hdr; icmp_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_icmp_hdr*, offset); PacketInfoIpv4Icmp* pkt_inf = new PacketInfoIpv4Icmp(mbuf, eth_hdr, ip4_hdr, icmp_hdr); return pkt_inf; } else { printf("packet is neither TCP UDP nor ICMP"); return new PacketInfo(mbuf, eth_hdr); } } else if (rte_be_to_cpu_16(eth_hdr->ether_type) == 0x86DD) { /// \TODO: implement IPv6 return new PacketInfo(mbuf, eth_hdr); } else if (rte_be_to_cpu_16(eth_hdr->ether_type) == 0x0806) { /// \TODO: implement ARP return new PacketInfo(mbuf, eth_hdr); } else { return new PacketInfo(mbuf, eth_hdr); } } /** * @brief Create a PacketInfo object for given packet type * * @param mbuf dpdk abstraction for one packet * @param type specifies Type which PacketInfo should have * @return PacketInfo* */ inline static PacketInfo* create_pkt_info(rte_mbuf* mbuf, PacketType type) { int off_set = sizeof(struct rte_ether_hdr); struct rte_ether_hdr* eth_hdr; rte_pktmbuf_append(mbuf, sizeof(struct rte_ether_hdr)); eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr*); switch (type) { case IPv4ICMP: { eth_hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); struct rte_ipv4_hdr* ip4_hdr; rte_pktmbuf_append(mbuf, sizeof(rte_ipv4_hdr)); ip4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr*, off_set); off_set = off_set + sizeof(rte_ipv4_hdr); rte_pktmbuf_append(mbuf, sizeof(rte_icmp_hdr)); rte_icmp_hdr* icmp_hdr; icmp_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_icmp_hdr*, off_set); return new PacketInfoIpv4Icmp(mbuf, eth_hdr, ip4_hdr, icmp_hdr); } break; case IPv4TCP: { eth_hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); // 0x0008 struct rte_ipv4_hdr* ip4_hdr; rte_pktmbuf_append(mbuf, sizeof(rte_ipv4_hdr) + sizeof(rte_tcp_hdr)); ip4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr*, off_set); off_set = off_set + sizeof(rte_ipv4_hdr); rte_tcp_hdr* tcp_hdr; tcp_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_tcp_hdr*, off_set); return new PacketInfoIpv4Tcp(mbuf, eth_hdr, ip4_hdr, tcp_hdr); } break; case IPv4UDP: { eth_hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); struct rte_ipv4_hdr* ip4_hdr; rte_pktmbuf_append(mbuf, sizeof(rte_ipv4_hdr)); ip4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr*, off_set); off_set = off_set + sizeof(rte_ipv4_hdr); rte_pktmbuf_append(mbuf, sizeof(rte_udp_hdr)); rte_udp_hdr* udp_hdr; udp_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_udp_hdr*, off_set); return new PacketInfoIpv4Udp(mbuf, eth_hdr, ip4_hdr, udp_hdr); } break; case IPv6ICMP: return new PacketInfo(mbuf, eth_hdr); break; case IPv6TCP: return new PacketInfo(mbuf, eth_hdr); break; case IPv6UDP: return new PacketInfo(mbuf, eth_hdr); break; default: return new PacketInfo(mbuf, eth_hdr); break; } } /** * @brief Create a minimalized PacketInfo * this Packet is expected to already have a filled ether header * and is only for IPv4 * @param mbuf dpdk abstraction for one packet * @param type specifies Type which PacketInfo should have * @return PacketInfo* */ inline static PacketInfo* create_mini_pkt_info(rte_mbuf* mbuf, PacketType type) { int off_set = sizeof(struct rte_ether_hdr); switch (type) { case IPv4TCP: { struct rte_ipv4_hdr* ip4_hdr; ip4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr*, off_set); off_set = off_set + sizeof(rte_ipv4_hdr); rte_tcp_hdr* tcp_hdr; tcp_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_tcp_hdr*, off_set); return new PacketInfoIpv4Tcp(mbuf, ip4_hdr, tcp_hdr); } break; case IPv4UDP: { struct rte_ipv4_hdr* ip4_hdr; ip4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr*, off_set); off_set = off_set + sizeof(rte_ipv4_hdr); rte_udp_hdr* udp_hdr; udp_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_udp_hdr*, off_set); return new PacketInfoIpv4Udp(mbuf, ip4_hdr, udp_hdr); } break; default: return nullptr; break; } } /** * @brief returns a packets destiantion ip * This method takes an mbuf and extract the IPv4 IP-adress. * In case the packet inside the mbuf is no IPv4 packet, 0 will be returned * @param mbuf structure to hand packets over * @return uint32_t packets IP-adress; it's 0, in case of no IPv4 */ inline static uint32_t get_dst_ip_from_mbuf(rte_mbuf* mbuf) { rte_ether_hdr* eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr*); if (eth_hdr->ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) { int off_set = sizeof(struct rte_ether_hdr); rte_ipv4_hdr* ip_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr*, off_set); return rte_be_to_cpu_32(ip_hdr->dst_addr); } else { return 0; } } inline static void destroy_pkt_info(PacketInfo* info) { PacketType type = info->get_type(); switch (type) { case IPv4TCP: { delete static_cast(info); } break; case IPv4UDP: { delete static_cast(info); } break; case NONE: { delete info; } break; case IPv4ICMP: { delete static_cast(info); } break; default: break; } } inline static bool is_ipv4_tcp(rte_mbuf* mbuf) { struct rte_ether_hdr* eth_hdr; eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr*); if (rte_be_to_cpu_16(eth_hdr->ether_type) == ETHER_TYPE_IPv4) { uint16_t offset = (uint16_t)sizeof(struct rte_ether_hdr); struct rte_ipv4_hdr* ip4_hdr; ip4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr*, offset); uint8_t protocol_id = ip4_hdr->next_proto_id; if (protocol_id == 6) { // TCP return true; } else { return false; } } else { return false; } } };