#include "../../include/packet/IP.hpp" #include #include #include #include #include #include #include #include uint16_t IP_class::get_payload_len() const { return payload_len; } TransportProtocol IP_class::get_protocol() const { return protocol; } std::string IP_class::get_source() { return src; } std::string IP_class::get_dest() { return dst; } /*** Ipv4 ***/ IPv4::IPv4(const u_char *data) { ip_hdr = reinterpret_cast(data); src = inet_ntoa(ip_hdr->ip_src); dst = inet_ntoa(ip_hdr->ip_dst); ip_hdr_len = ip_hdr->ip_hl * 4; if (ip_hdr_len < 20) { throw std::runtime_error("Failed to initial IPv4 "); } switch (ip_hdr->ip_p) { case IPPROTO_TCP: IPv4::handle_tcp(); break; case IPPROTO_UDP: IPv4::handle_udp(); break; case IPPROTO_ICMP: IPv4::handle_icmp(); break; case IPPROTO_ICMPV6: IPv4::handle_icmpv6(); break; case IPPROTO_IGMP: IPv4::handle_igmp(); break; default: protocol = TransportProtocol::UNKNOWN; break; } } void IPv4::handle_tcp() { const auto *tcp = reinterpret_cast(reinterpret_cast(ip_hdr) + ip_hdr_len); src_port = ntohs(tcp->source); dest_port = ntohs(tcp->dest); payload_ptr = reinterpret_cast(tcp) + tcp->doff * 4; payload_len = ntohs(ip_hdr->ip_len) - (ip_hdr_len + tcp->doff * 4); protocol = TransportProtocol::TCP; } void IPv4::handle_udp() { const auto *udp = reinterpret_cast(reinterpret_cast(ip_hdr) + ip_hdr_len); dest_port = ntohs(udp->dest); src_port = ntohs(udp->source); payload_ptr = reinterpret_cast(udp) + sizeof(udphdr); payload_len = ntohs(udp->len) - sizeof(udphdr); protocol = TransportProtocol::UDP; } void IPv4::handle_icmp() { protocol = TransportProtocol::ICMP; } void IPv4::handle_icmpv6() { protocol = TransportProtocol::ICMP6; } void IPv4::handle_igmp() { protocol = TransportProtocol::IGMP; } uint16_t IPv4::get_src_port() { return src_port; } uint16_t IPv4::get_dest_port() { return dest_port; } /*** Ipv6 ***/ IPv6::IPv6(const u_char *data) { ip_hdr = reinterpret_cast(data); uint8_t hdr = ip_hdr->ip6_nxt; std::array src{}; inet_ntop(AF_INET6, &ip_hdr->ip6_src, src.data(), sizeof(src)); this->src = src.data(); std::array dst{}; inet_ntop(AF_INET6, &ip_hdr->ip6_dst, dst.data(), sizeof(dst)); this->dst = dst.data(); ptr = reinterpret_cast(ip_hdr + 1); while (true) { switch (hdr) { case IPPROTO_TCP: IPv6::handle_tcp(); return; case IPPROTO_UDP: IPv6::handle_udp(); return; case IPPROTO_ICMP: IPv6::handle_icmp(); return; case IPPROTO_ICMPV6: IPv6::handle_icmpv6(); return; case IPPROTO_IGMP: IPv6::handle_igmp(); return; /* if we have an extension headers, dont leave from loop, * keep find a protocol type */ case IPPROTO_HOPOPTS: case IPPROTO_ROUTING: case IPPROTO_DSTOPTS: { const auto *ext = reinterpret_cast(ptr); hdr = ext->ip6e_nxt; ptr += (ext->ip6e_len + 1) * 8; break; } case IPPROTO_FRAGMENT: { const auto *frag = reinterpret_cast(ptr); hdr = frag->ip6f_nxt; ptr += sizeof(ip6_frag); break; } default: protocol = TransportProtocol::UNKNOWN; return; } } ptr = nullptr; } void IPv6::handle_tcp() { const auto tcp = reinterpret_cast(ptr); dest_port = ntohs(tcp->dest); src_port = ntohs(tcp->source); payload_ptr = reinterpret_cast(tcp) + tcp->doff * 4; payload_len = ntohs(ip_hdr->ip6_plen) - tcp->doff * 4; protocol = TransportProtocol::TCP; ptr = nullptr; } void IPv6::handle_udp() { const auto udp = reinterpret_cast(ptr); dest_port = ntohs(udp->dest); src_port = ntohs(udp->source); payload_ptr = reinterpret_cast(udp) + sizeof(udphdr); payload_len = ntohs(udp->len) - sizeof(udphdr); protocol = TransportProtocol::UDP; ptr = nullptr; } void IPv6::handle_icmp() { protocol = TransportProtocol::ICMP; ptr = nullptr; } void IPv6::handle_icmpv6() { protocol = TransportProtocol::ICMP6; payload_len = ntohs(ip_hdr->ip6_plen) - sizeof(icmp6_hdr); ptr = nullptr; } void IPv6::handle_igmp() { protocol = TransportProtocol::IGMP; ptr = nullptr; } uint16_t IPv6::get_src_port() { return src_port; } uint16_t IPv6::get_dest_port() { return dest_port; }