290 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			290 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /**
 | |
|  * @file PacketInfoCreator.hpp
 | |
|  * @author Tobias
 | |
|  * @brief
 | |
|  * @date 2021-06-16
 | |
|  */
 | |
| #pragma once
 | |
| 
 | |
| #include <rte_ether.h>
 | |
| 
 | |
| #include <boost/log/trivial.hpp>
 | |
| 
 | |
| #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<PacketInfoIpv4Tcp*>(info);
 | |
|         } break;
 | |
| 
 | |
|         case IPv4UDP: {
 | |
|             delete static_cast<PacketInfoIpv4Udp*>(info);
 | |
|         } break;
 | |
| 
 | |
|         case NONE: {
 | |
|             delete info;
 | |
|         } break;
 | |
|         case IPv4ICMP: {
 | |
|             delete static_cast<PacketInfoIpv4Icmp*>(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;
 | |
|         }
 | |
|     }
 | |
| }; |