1 //-------------------------------------------------------------------------- 2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved. 3 // 4 // This program is free software; you can redistribute it and/or modify it 5 // under the terms of the GNU General Public License Version 2 as published 6 // by the Free Software Foundation. You may not use, modify or distribute 7 // this program under any other version of the GNU General Public License. 8 // 9 // This program is distributed in the hope that it will be useful, but 10 // WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 // General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License along 15 // with this program; if not, write to the Free Software Foundation, Inc., 16 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 //-------------------------------------------------------------------------- 18 // packet_manager.h author Josh Rosenbaum <jrosenba@cisco.com> 19 20 #ifndef PACKET_MANAGER_H 21 #define PACKET_MANAGER_H 22 23 // PacketManager provides decode and encode services by leveraging Codecs. 24 25 #include <array> 26 27 #include "framework/codec.h" 28 #include "framework/counts.h" 29 #include "main/snort_types.h" 30 #include "managers/codec_manager.h" 31 #include "protocols/packet.h" 32 33 struct TextLog; 34 35 namespace snort 36 { 37 struct Packet; 38 39 enum class TcpResponse 40 { 41 FIN, 42 RST, 43 PUSH, 44 }; 45 46 enum class UnreachResponse 47 { 48 NET, 49 HOST, 50 PORT, 51 FWD, 52 }; 53 54 // FIXIT-M roll the PacketManager and 'layer' namespace into the Packet 55 // struct 56 57 class SO_PUBLIC PacketManager 58 { 59 public: 60 static void thread_init(); 61 static void thread_term(); 62 63 // decode this packet and set all relevant packet fields. 64 static void decode(Packet*, const struct _daq_pkt_hdr*, const uint8_t* pkt, 65 uint32_t pktlen, bool cooked = false, bool retry = false); 66 67 // update the packet's checksums and length variables. Call this function 68 // after Snort has changed any data in this packet 69 static void encode_update(Packet*); 70 71 //-------------------------------------------------------------------- 72 // FIXIT-L encode_format() should be replaced with a function that 73 // does format and update in one step for packets cooked for internal 74 // use only like stream_tcp and port_scan. stream_ip packets should 75 // just be decoded from last layer on. at that point all the 76 // Codec::format methods can be deleted too. the new function should 77 // be some super set of format_tcp(). 78 //-------------------------------------------------------------------- 79 80 // format packet for detection. Original ttl is always used. orig is 81 // the wire pkt; clone was obtained with New() 82 static int encode_format( 83 EncodeFlags, const Packet* orig, Packet* clone, 84 PseudoPacketType, const DAQ_PktHdr_t* = nullptr, uint32_t opaque = 0); 85 86 static int format_tcp( 87 EncodeFlags, const Packet* orig, Packet* clone, PseudoPacketType, 88 const DAQ_PktHdr_t* = nullptr, uint32_t opaque = 0); 89 90 // Send a TCP response. TcpResponse params determined the type 91 // of response. Len will be set to the response's length. 92 // payload && payload_len are optional. 93 static const uint8_t* encode_response( 94 TcpResponse, EncodeFlags, const Packet* orig, uint32_t& len, 95 const uint8_t* const payload = nullptr, uint32_t payload_len = 0); 96 97 // Send an ICMP unreachable response! 98 static const uint8_t* encode_reject( 99 UnreachResponse, EncodeFlags, const Packet*, uint32_t& len); 100 101 /* codec support and statistics */ 102 103 // get the max payload for the current packet 104 static uint16_t encode_get_max_payload(const Packet*); 105 106 // print codec information. MUST be called after thread_term. 107 static void dump_stats(); 108 109 static void reset_stats(); 110 111 // Get the name of the given protocol ID 112 static const char* get_proto_name(ProtocolId); 113 114 // Get the name of the given IP protocol 115 static const char* get_proto_name(IpProtocol); 116 117 // print this packets information, layer by layer 118 static void log_protocols(TextLog* const, const Packet* const); 119 120 /* Accessor functions -- any object in Snort++ can now convert a 121 * protocol to its mapped value. 122 * 123 * The equivalent of Snort's PROTO_ID */ max_protocols()124 static constexpr std::size_t max_protocols() // compile time constant 125 { return CodecManager::s_protocols.size(); } 126 127 /* If a proto was registered in a Codec's get_protocol_ids() function, 128 * this function will return the 'ProtocolIndex' of the Codec to which the proto belongs. 129 * If none of the loaded Codecs registered that proto, this function will 130 * return zero. */ proto_idx(ProtocolId prot_id)131 static ProtocolIndex proto_idx(ProtocolId prot_id) 132 { return CodecManager::s_proto_map[to_utype(prot_id)]; } 133 134 static void accumulate(); 135 136 private: 137 static bool push_layer(Packet*, CodecData&, ProtocolId, const uint8_t* hdr_start, uint32_t len); 138 static Codec* get_layer_codec(const Layer&, int idx); 139 static void pop_teredo(Packet*, RawData&); 140 static void handle_decode_failure(Packet*, RawData&, const CodecData&, const DecodeData&, ProtocolId); 141 142 static bool encode(const Packet*, EncodeFlags, 143 uint8_t lyr_start, IpProtocol next_prot, Buffer& buf); 144 145 // constant offsets into the s_stats array. Notice the stat_offset 146 // constant which is used when adding a protocol specific codec 147 static const uint8_t total_processed = 0; 148 static const uint8_t other_codecs = 1; 149 static const uint8_t discards = 2; 150 static const uint8_t depth_exceeded = 3; 151 static const uint8_t stat_offset = 4; 152 153 // declared in header so it can access s_protocols 154 static THREAD_LOCAL std::array<PegCount, stat_offset + 155 CodecManager::s_protocols.size()> s_stats; 156 // FIXIT-L gcc apparently does not consider thread_local variables to be valid in 157 // constexpr expressions. As long as __thread is used instead of thread_local in gcc, 158 // this is not a problem. However, if we use thread_local and gcc, the declaration 159 // below will not compile. 160 static std::array<PegCount, s_stats.size()> g_stats; 161 static const std::array<const char*, stat_offset> stat_names; 162 }; 163 } 164 #endif 165 166