/* * Copyright (c) 2017-2024 OARC, Inc. * Copyright (c) 2011-2017, IIS - The Internet Foundation in Sweden * All rights reserved. * * This file is part of PacketQ. * * PacketQ is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * PacketQ is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with PacketQ. If not, see . */ #include "icmp.h" #include "output.h" #include "packet_handler.h" #include "packetq.h" #include "tcp.h" #include #include #include namespace packetq { Parse_icmp::Parse_icmp() { table_name = "icmp"; add_packet_columns(); add_lookup_tables(); } void Parse_icmp::add_packet_columns() { m_ip_helper.add_packet_columns(*this); add_packet_column("type", "", Coltype::_int, COLUMN_TYPE); add_packet_column("code", "", Coltype::_int, COLUMN_CODE); add_packet_column("echo_identifier", "", Coltype::_int, COLUMN_ECHO_IDENTIFIER); add_packet_column("echo_sequence", "", Coltype::_int, COLUMN_ECHO_SEQUENCE); add_packet_column("du_protocol", "", Coltype::_int, COLUMN_DU_PROTOCOL); add_packet_column("du_src_addr", "", Coltype::_text, COLUMN_DU_SRC_ADDR); add_packet_column("du_dst_addr", "", Coltype::_text, COLUMN_DU_DST_ADDR); add_packet_column("desc", "", Coltype::_text, COLUMN_DESC); } void Parse_icmp::add_lookup_tables() { } Packet::ParseResult Parse_icmp::parse(Packet& packet, const std::vector& columns, Row& destination_row, bool sample) { if (packet.m_ip_header.proto != IPPROTO_ICMP) return Packet::ERROR; if (packet.m_ip_header.ethertype != 2048) // we dont support ICMPv6 yet return Packet::ERROR; if (!sample) return Packet::NOT_SAMPLED; if (packet.m_len < 2) return Packet::ERROR; Row* r = &destination_row; m_ip_helper.assign(r, &packet.m_ip_header, columns); unsigned char* raw = packet.m_data; int type = raw[0]; int code = raw[1]; int identifier = 0, sequence = 0, protocol = 0; RefCountString *src_addr = 0, *dst_addr = 0; bool src_addr_used = false, dst_addr_used = false; switch (type) { case 0: if (packet.m_len < 8) return Packet::ERROR; identifier = get_short(&raw[4]); sequence = get_short(&raw[6]); break; case 3: { IP_header head; if (packet.m_len < 8 + 20) return Packet::ERROR; head.decode(&raw[8], packet.m_ip_header.ethertype, 0); protocol = head.proto; src_addr = v4_addr2str(head.src_ip); dst_addr = v4_addr2str(head.dst_ip); } break; case 8: if (packet.m_len < 8) return Packet::ERROR; identifier = get_short(&raw[4]); sequence = get_short(&raw[6]); break; } for (auto i = columns.begin(), end = columns.end(); i != end; ++i) { switch (*i) { case COLUMN_TYPE: acc_type.value(r) = type; break; case COLUMN_CODE: acc_code.value(r) = code; break; case COLUMN_ECHO_IDENTIFIER: acc_echo_identifier.value(r) = identifier; break; case COLUMN_ECHO_SEQUENCE: acc_echo_sequence.value(r) = sequence; break; case COLUMN_DU_PROTOCOL: acc_du_protocol.value(r) = protocol; break; case COLUMN_DU_SRC_ADDR: acc_du_src_addr.value(r) = src_addr ? src_addr : RefCountString::construct(""); src_addr_used = true; break; case COLUMN_DU_DST_ADDR: acc_du_dst_addr.value(r) = dst_addr ? dst_addr : RefCountString::construct(""); dst_addr_used = true; break; case COLUMN_DESC: switch (type) { case 0: acc_desc.value(r) = RefCountString::construct("Echo Reply"); break; case 3: switch (code) { case 0: acc_desc.value(r) = RefCountString::construct("Destination network unreachable"); break; case 1: acc_desc.value(r) = RefCountString::construct("Destination host unreachable"); break; case 2: acc_desc.value(r) = RefCountString::construct("Destination protocol unreachable"); break; case 3: acc_desc.value(r) = RefCountString::construct("Destination port unreachable"); break; default: acc_desc.value(r) = RefCountString::construct("Destination unreachable"); break; } break; case 4: acc_desc.value(r) = RefCountString::construct("Source quench"); break; case 5: acc_desc.value(r) = RefCountString::construct("Redirect Message"); break; case 6: acc_desc.value(r) = RefCountString::construct("Alternate Host Address"); break; case 8: acc_desc.value(r) = RefCountString::construct("Echo Request"); break; case 9: acc_desc.value(r) = RefCountString::construct("Router Advertisement"); break; case 10: acc_desc.value(r) = RefCountString::construct("Router Solicitation"); break; case 11: acc_desc.value(r) = RefCountString::construct("Time Exceeded"); break; case 12: acc_desc.value(r) = RefCountString::construct("Bad IP header"); break; case 13: acc_desc.value(r) = RefCountString::construct("Timestamp"); break; case 14: acc_desc.value(r) = RefCountString::construct("Timestamp Reply"); break; case 15: acc_desc.value(r) = RefCountString::construct("Information Request"); break; case 16: acc_desc.value(r) = RefCountString::construct("Information Reply"); break; case 17: acc_desc.value(r) = RefCountString::construct("Address Mask Request"); break; case 18: acc_desc.value(r) = RefCountString::construct("Address Mask Reply"); break; case 30: acc_desc.value(r) = RefCountString::construct("Traceroute"); break; default: acc_desc.value(r) = RefCountString::construct("UNKNOWN TYPE"); } break; } } if (src_addr && !src_addr_used) src_addr->dec_refcount(); if (dst_addr && !dst_addr_used) dst_addr->dec_refcount(); return Packet::OK; } void Parse_icmp::on_table_created(Table* table, const std::vector& columns) { m_ip_helper.on_table_created(table, columns); acc_type = table->get_accessor("type"); acc_code = table->get_accessor("code"); acc_echo_identifier = table->get_accessor("echo_identifier"); acc_echo_sequence = table->get_accessor("echo_sequence"); acc_du_protocol = table->get_accessor("du_protocol"); acc_du_src_addr = table->get_accessor("du_src_addr"); acc_du_dst_addr = table->get_accessor("du_dst_addr"); acc_desc = table->get_accessor("desc"); } } // namespace packetq