00001 //--------------------------------------------------------------------------
00002 // Copyright (C) 2014-2017 Cisco and/or its affiliates. All rights reserved.
00003 //
00004 // This program is free software; you can redistribute it and/or modify it
00005 // under the terms of the GNU General Public License Version 2 as published
00006 // by the Free Software Foundation. You may not use, modify or distribute
00007 // this program under any other version of the GNU General Public License.
00008 //
00009 // This program is distributed in the hope that it will be useful, but
00010 // WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License along
00015 // with this program; if not, write to the Free Software Foundation, Inc.,
00016 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017 //--------------------------------------------------------------------------
00018 // codec.h author Josh Rosenbaum <jrosenba@cisco.com>
00019
00020 #ifndef FRAMEWORK_CODEC_H
00021 #define FRAMEWORK_CODEC_H
00022
00023 // Codec is a type of plugin that provides protocol-specific encoding and
00024 // decoding.
00025
00026 #include <cstdint>
00027 #include <vector>
00028
00029 #include "framework/base_api.h"
00030 #include "framework/decode_data.h"
00031 #include "utils/cpp_macros.h"
00032
00033 struct TextLog;
00034 struct _daq_pkthdr;
00035 struct Packet;
00036 struct Layer;
00037 class Flow;
00038 enum CodecSid : uint32_t;
00039
00040 namespace ip
00041 {
00042 class IpApi;
00043 }
00044 namespace tcp
00045 {
00046 struct TCPHdr;
00047 }
00048 namespace udp
00049 {
00050 struct UDPHdr;
00051 }
00052 namespace icmp
00053 {
00054 struct ICMPHdr;
00055 }
00056
00057 // Used by root codecs to add their DLT to their HELP string
00058 #define ADD_DLT(help, x) help " (DLT " STRINGIFY_MX(x) ")"
00059
00060 constexpr uint8_t MIN_TTL = 64;
00061 constexpr uint8_t MAX_TTL = 255;
00062
00063 struct RawData
00064 {
00065 const _daq_pkthdr* pkth;
00066 const uint8_t* data;
00067 uint32_t len;
00068
00069 RawData(const _daq_pkthdr*, const uint8_t*);
00070 };
00071
00072 /* Decode Flags */
00073 constexpr uint16_t CODEC_DF = 0x0001; /* don't fragment flag */
00074
00075 // packet may have incorrect encapsulation layer. don't alert if "next
00076 // layer" is invalid. If decode fails with this bit set, PacketManager
00077 // will back out to the previous layer. IMPORTANT: This bit can ONLY be
00078 // set if the DECODE_ENCAP_LAYER flag was was previously set.
00079 constexpr uint16_t CODEC_UNSURE_ENCAP = 0x0002;
00080
00081 // DO NOT USE THIS LAYER!! -- use DECODE_ENCAP_LAYER
00082 constexpr uint16_t CODEC_SAVE_LAYER = 0x0004;
00083
00084 // If encapsulation decode fails, back out to this layer This will be
00085 // cleared by PacketManager between decodes This flag automatically sets
00086 // DECODE_ENCAP_LAYER for the next layer (and only the next layer).
00087 constexpr uint16_t CODEC_ENCAP_LAYER = (CODEC_SAVE_LAYER | CODEC_UNSURE_ENCAP );
00088
00089 // used to check ip6 extension order
00090 constexpr uint16_t CODEC_ROUTING_SEEN = 0x0008;
00091
00092 // used by icmp4 for alerting
00093 constexpr uint16_t CODEC_IPOPT_RR_SEEN = 0x0010;
00094
00095 // used by IGMP for alerting
00096 constexpr uint16_t CODEC_IPOPT_RTRALT_SEEN = 0x0020;
00097
00098 // used by IGMP for alerting
00099 constexpr uint16_t CODEC_IPOPT_LEN_THREE = 0x0040;
00100
00101 // used in IPv6 Codec
00102 constexpr uint16_t CODEC_TEREDO_SEEN = 0x0080;
00103
00104 constexpr uint16_t CODEC_STREAM_REBUILT = 0x0100;
00105 constexpr uint16_t CODEC_NON_IP_TUNNEL = 0x0200;
00106
00107 constexpr uint16_t CODEC_IP6_EXT_OOO = 0x0400;
00108 constexpr uint16_t CODEC_IP6_BAD_OPT = 0x0800;
00109
00110 constexpr uint16_t CODEC_ETHER_NEXT = 0x1000;
00111
00112 constexpr uint16_t CODEC_IPOPT_FLAGS = (CODEC_IPOPT_RR_SEEN |
00113 CODEC_IPOPT_RTRALT_SEEN | CODEC_IPOPT_LEN_THREE);
00114
00115 struct CodecData
00116 {
00117 /* This section will get reset before every decode() function call */
00118 ProtocolId next_prot_id; /* protocol type of the next layer */
00119 uint16_t lyr_len; /* The length of the valid part layer */
00120 uint16_t invalid_bytes; /* the length of the INVALID part of this layer */
00121
00122 /* Reset before each decode of packet begins */
00123
00124 /* Codec specific fields. These fields are only relevant to codecs. */
00125 uint16_t proto_bits; /* protocols contained within this packet
00126 -- will be propogated to Snort++ Packet struct*/
00127 uint16_t codec_flags; /* flags used while decoding */
00128 uint8_t ip_layer_cnt;
00129
00130 /* The following values have junk values after initialization */
00131 uint8_t ip6_extension_count; /* initialized in cd_ipv6.cc */
00132 uint8_t curr_ip6_extension; /* initialized in cd_ipv6.cc */
00133 IpProtocol ip6_csum_proto; /* initialized in cd_ipv6.cc. Used for IPv6 checksums */
00134
00135 CodecData(ProtocolId init_prot) : next_prot_id(init_prot), lyr_len(0),
00136 invalid_bytes(0), proto_bits(0), codec_flags(0), ip_layer_cnt(0)
00137 { }
00138
00139 bool inline is_cooked() const
00140 { return codec_flags & CODEC_STREAM_REBUILT; }
00141 };
00142
00143 typedef uint64_t EncodeFlags;
00144 constexpr EncodeFlags ENC_FLAG_FWD = 0x8000000000000000; // send in forward direction
00145 constexpr EncodeFlags ENC_FLAG_SEQ = 0x4000000000000000; // VAL bits contain seq adj
00146 constexpr EncodeFlags ENC_FLAG_ID = 0x2000000000000000; // use randomized IP ID
00147 constexpr EncodeFlags ENC_FLAG_NET = 0x1000000000000000; // stop after innermost network (ip4/6)
00148 // layer
00149 constexpr EncodeFlags ENC_FLAG_DEF = 0x0800000000000000; // stop before innermost ip4 opts or ip6
00150 // frag header
00151 constexpr EncodeFlags ENC_FLAG_RAW = 0x0400000000000000; // don't encode outer eth header (this is
00152 // raw ip)
00153 constexpr EncodeFlags ENC_FLAG_PAY = 0x0200000000000000; // set to when a TCP payload is attached
00154 constexpr EncodeFlags ENC_FLAG_PSH = 0x0100000000000000; // set by PacketManager when TCP should
00155 // set PUSH flag
00156 constexpr EncodeFlags ENC_FLAG_FIN = 0x0080000000000000; // set by PacketManager when TCP should
00157 // set FIN flag
00158 constexpr EncodeFlags ENC_FLAG_TTL = 0x0040000000000000; // set by PacketManager when TCP should
00159 // set FIN flag
00160 constexpr EncodeFlags ENC_FLAG_INLINE = 0x0020000000000000; // set by PacketManager when TCP
00161 // should set FIN flag
00162 constexpr EncodeFlags ENC_FLAG_RST_CLNT = 0x0010000000000000; // finish with a client RST packet
00163 constexpr EncodeFlags ENC_FLAG_RST_SRVR = 0x0008000000000000; // finish with a server RST packet
00164 constexpr EncodeFlags ENC_FLAG_VAL = 0x00000000FFFFFFFF; // bits for adjusting seq and/or ack
00165
00166 constexpr uint8_t ENC_PROTO_UNSET = 0xFF;
00167
00168 struct SO_PUBLIC EncState
00169 {
00170 const ip::IpApi& ip_api; /* IP related information. Good for checksums */
00171 EncodeFlags flags;
00172 const uint16_t dsize; /* for non-inline, TCP sequence numbers */
00173 ProtocolId next_ethertype; /* set the next encoder 'proto' field to this value. */
00174 IpProtocol next_proto; /* set the next encoder 'proto' field to this value. */
00175 const uint8_t ttl;
00176
00177 EncState(const ip::IpApi& api, EncodeFlags f, IpProtocol pr,
00178 uint8_t t, uint16_t data_size);
00179
00180 inline bool next_proto_set() const
00181 { return (next_proto != IpProtocol::PROTO_NOT_SET); }
00182
00183 inline bool ethertype_set() const
00184 { return next_ethertype != ProtocolId::ETHERTYPE_NOT_SET; }
00185
00186 inline bool forward() const
00187 { return flags & ENC_FLAG_FWD; }
00188
00189 uint8_t get_ttl(uint8_t lyr_ttl) const;
00190 };
00191
00192 struct SO_PUBLIC Buffer
00193 {
00194 public:
00195 Buffer(uint8_t* buf, uint32_t size);
00196
00197 inline uint8_t* data() const
00198 { return base; }
00199
00200 uint32_t size() const
00201 { return end; }
00202
00203 inline bool allocate(uint32_t len)
00204 {
00205 if ( (end + len) > max_len )
00206 return false;
00207
00208 end += len;
00209 base -= len;
00210 return true;
00211 }
00212
00213 inline void clear()
00214 { base = base + end; end = 0; off = 0; }
00215
00216 private:
00217 uint8_t* base; /* start of data */
00218 uint32_t end; /* end of data */
00219 const uint32_t max_len; /* size of allocation */
00220
00221 public:
00222 uint32_t off; /* offset into data */
00223 };
00224
00225 typedef uint8_t UpdateFlags;
00226 constexpr UpdateFlags UPD_COOKED = 0x01;
00227 constexpr UpdateFlags UPD_MODIFIED = 0x02;
00228 constexpr UpdateFlags UPD_RESIZED = 0x04;
00229 constexpr UpdateFlags UPD_REBUILT_FRAG = 0x08;
00230
00231 /* Codec Class */
00232
00233 class SO_PUBLIC Codec
00234 {
00235 public:
00236 virtual ~Codec() = default;
00237
00238 // PKT_MAX = ETHERNET_HEADER_LEN + VLAN_HEADER + ETHERNET_MTU + IP_MAXPACKET
00239
00240 /* PKT_MAX is sized to ensure that any reassembled packet
00241 * can accommodate a full datagram at innermost layer
00242 *
00243 * ETHERNET_HEADER_LEN == 14
00244 * VLAN_HEADER == 4
00245 * ETHERNET_MTU == 1500
00246 * IP_MAXPACKET == 65535 FIXIT-L use Packet::max_dsize
00247 */
00248 static const uint32_t PKT_MAX = 14 + 4 + 1500 + 65535;
00249
00250 /* Codec Initialization */
00251
00252 // Get the codec's name
00253 inline const char* get_name() const
00254 { return name; }
00255 // Registers this Codec's data link type (as defined by libpcap)
00256 virtual void get_data_link_type(std::vector<int>&) // FIXIT-M return a vector == efficient in
00257 // c++11
00258 { }
00259 // Register the code's protocol ID's and Ethertypes
00260 virtual void get_protocol_ids(std::vector<ProtocolId>&) // FIXIT-M return a vector ==
00261 // efficient in c++11
00262 { }
00263
00264 /*
00265 * Main decoding function! Will get called when decoding a packet.
00266 *
00267 * PARAMS:
00268 * const RawData& = struct containing information about the
00269 * current packet's raw data
00270 *
00271 * CodecData& = Pass information the PacketManager and other
00272 * codecs. IMPORTANT FIELDS TO SET IN YOUR CODEC -
00273 * next_prot_id = protocol type of the next layer
00274 * lyr_len = The length of the valid part layer
00275 * invalid bytes = number of invalid bytes between the end of
00276 * the this layer's valid length and the next
00277 * layer. For instance,
00278 * when decoding IP, if there are 20 bytes of
00279 * options but only 12 bytes are valid.
00280 *
00281 * data.lyr_len = MIN_IP_HEADER_LEN + 12;
00282 * data.invalid_bytes = 8 === 20 - 12
00283 *
00284 * DecodeData& = Data which will be sent to the rest of Snort++.
00285 * contains convenience pointers and information
00286 * about this packet.
00287 **/
00288 virtual bool decode(const RawData&, CodecData&, DecodeData&)=0;
00289
00290 /*
00291 * Log this layer's information
00292 * PARAMS:
00293 * TextLog* = the logger. Defined in "text_log.h"
00294 * const uint8_t *raw_pkt = the same data seen during decode
00295 * const uint16_t lyr_len = This layer's validated length ==
00296 * lyr_len set during decode.
00297 */
00298 virtual void log(TextLog* const, const uint8_t* /*raw_pkt*/, const uint16_t /*lyr_len*/)
00299 { }
00300
00301 /*
00302 * Encoding -- active response!!
00303 *
00304 * Encode the current packet. Encoding starts with the innermost
00305 * layer and working outwards. All encoders MUST call the
00306 * Buffer.allocate() function before writing to output buffer.
00307 * PARAMS:
00308 * uint8_t* raw_in = A pointer to the raw input which was decoded.
00309 * This is the same pointer which was given to decode().
00310 * uint16_t len == the value to which '(CodecData&).lyr_len' was set during decode.
00311 * I.e., the validated length of this layer. Some protocols,
00312 * like IPv4 (original ipv4 header may contain invalid options
00313 * which we don't want to copy) and GTP have dynamic lengths.
00314 * So, this parameter ensure the encode() function doesn't
00315 * need to revalidate and recalculate the length.
00316 * EncState& = The current EncState struct
00317 * Buffer& = the packet which will be sent. All inward layers will already
00318 * be set.
00319 *
00320 * NOTE: all functions MUST call the Buffer.allocate() function before
00321 * manipulating memory.
00322 */
00323 virtual bool encode(const uint8_t* const /*raw_in */,
00324 const uint16_t /*raw_len*/,
00325 EncState&,
00326 Buffer&, Flow*)
00327 { return true; }
00328
00329 /*
00330 * Update this layers checksums and length fields. Used
00331 * when rebuilding packets and Snort is in inline mode.
00332 *
00333 * updated_len MUST be set to this layers updated length.
00334 */
00335 virtual void update(
00336 const ip::IpApi&,
00337 const EncodeFlags /*flags*/,
00338 uint8_t* /*raw_pkt*/, /* The data associated with the current layer */
00339 uint16_t lyr_len, /* This layers previously calculated length */
00340 uint32_t& updated_len) /* Update! The length to end of packet */
00341 { updated_len += lyr_len; }
00342
00343 // formatter
00344 virtual void format(bool /*reverse*/, uint8_t* /*raw_pkt*/, DecodeData&)
00345 { }
00346
00347 protected:
00348 Codec(const char* s)
00349 { name = s; }
00350
00351 // Create an event with the Codec GID
00352 void codec_event(const CodecData &, CodecSid);
00353 // Check the Hop and DST IPv6 extension
00354 bool CheckIPV6HopOptions(const RawData&, CodecData&);
00355 // NOTE:: data.next_prot_id MUST be set before calling this!!
00356 void CheckIPv6ExtensionOrder(CodecData&, const IpProtocol);
00357
00358 private:
00359 const char* name;
00360 };
00361
00362 //-------------------------------------------------------------------------
00363 // api
00364 //-------------------------------------------------------------------------
00365
00366 // this is the current version of the api
00367 #define CDAPI_VERSION ((BASE_API_VERSION << 16) | 0)
00368
00369 typedef Codec* (* CdNewFunc)(Module*);
00370 typedef void (* CdDelFunc)(Codec*);
00371 typedef void (* CdAuxFunc)();
00372
00373 struct CodecApi
00374 {
00375 BaseApi base;
00376
00377 // these may be nullptr
00378 CdAuxFunc pinit; // initialize global plugin data
00379 CdAuxFunc pterm; // clean-up pinit()
00380
00381 CdAuxFunc tinit; // initialize thread-local plugin data
00382 CdAuxFunc tterm; // clean-up tinit()
00383
00384 // these must be set
00385 CdNewFunc ctor; // get eval optional instance data
00386 CdDelFunc dtor; // clean up instance data
00387 };
00388
00389 #endif /* FRAMEWORK_CODEC_H */
00390
END OF CODE