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