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.h author Josh Rosenbaum <jrosenba@cisco.com>
19 
20 #ifndef PROTOCOLS_PACKET_H
21 #define PROTOCOLS_PACKET_H
22 
23 #include <daq_common.h>
24 
25 #include "flow/flow.h"
26 #include "framework/decode_data.h"
27 #include "main/snort_types.h"
28 #include "target_based/snort_protocols.h"
29 
30 // Event that is generated when a packet without a flow is processed
31 #define PKT_WITHOUT_FLOW_EVENT  "non_flow_pkt"
32 
33 namespace snort
34 {
35 class Active;
36 class Endianness;
37 class Flow;
38 class ActiveAction;
39 class IpsContext;
40 class Obfuscator;
41 class SFDAQInstance;
42 
43 /* packet status flags */
44 #define PKT_REBUILT_FRAG     0x00000001  /* is a rebuilt fragment */
45 #define PKT_REBUILT_STREAM   0x00000002  /* is a rebuilt stream */
46 #define PKT_STREAM_UNEST_UNI 0x00000004  /* is from an unestablished stream and
47                                           * we've only seen traffic in one direction */
48 #define PKT_STREAM_EST       0x00000008  /* is from an established stream */
49 
50 #define PKT_STREAM_INSERT    0x00000010  /* this packet has been queued for stream reassembly */
51 #define PKT_STREAM_TWH       0x00000020  /* packet completes the 3-way handshake */
52 #define PKT_FROM_SERVER      0x00000040  /* this packet came from the server
53                                             side of a connection (TCP) */
54 #define PKT_FROM_CLIENT      0x00000080  /* this packet came from the client
55                                             side of a connection (TCP) */
56 
57 #define PKT_PDU_HEAD         0x00000100  /* start of PDU */
58 #define PKT_PDU_TAIL         0x00000200  /* end of PDU */
59 #define PKT_DETECT_LIMIT     0x00000400  /* alt_dsize is valid */
60 
61 #define PKT_ALLOW_MULTIPLE_DETECT 0x00000800  /* packet has multiple PDUs */
62 #define PKT_PAYLOAD_OBFUSCATE     0x00001000
63 
64 #define PKT_STATELESS        0x00002000  /* Packet has matched a stateless rule */
65 #define PKT_PASS_RULE        0x00004000  /* this packet has matched a pass rule */
66 #define PKT_IP_RULE          0x00008000  /* this packet is being evaluated against an IP rule */
67 #define PKT_IP_RULE_2ND      0x00010000  /* this packet is being evaluated against an IP rule */
68 
69 #define PKT_PSEUDO           0x00020000  /* is a pseudo packet */
70 #define PKT_MODIFIED         0x00040000  /* packet had normalizations, etc. */
71 #define PKT_RESIZED          0x00080000  /* packet has new size */
72 
73 // neither of these flags will be set for (full) retransmissions or non-data segments
74 // a partial overlap results in out of sequence condition
75 // out of sequence condition is sticky
76 #define PKT_STREAM_ORDER_OK  0x00100000  /* this segment is in order, w/o gaps */
77 #define PKT_STREAM_ORDER_BAD 0x00200000  /* this stream had at least one gap */
78 
79 #define PKT_FILE_EVENT_SET   0x00400000
80 #define PKT_IGNORE           0x00800000  /* this packet should be ignored, based on port */
81 #define PKT_RETRANSMIT       0x01000000  // packet is a re-transmitted pkt.
82 #define PKT_RETRY            0x02000000  /* this packet is being re-evaluated from the internal retry queue */
83 #define PKT_USE_DIRECT_INJECT 0x04000000  /* Use ioctl when injecting. */
84 #define PKT_HAS_PARENT       0x08000000  /* derived pseudo packet from current wire packet */
85 
86 #define PKT_WAS_SET          0x10000000  /* derived pseudo packet (PDU) from current wire packet */
87 
88 #define PKT_MORE_TO_FLUSH    0x20000000 /* when more data is available to StreamSplitter::scan */
89 
90 #define PKT_UNUSED_FLAGS     0xC0000000
91 
92 #define PKT_TS_OFFLOADED        0x01
93 
94 #define PKT_PDU_FULL (PKT_PDU_HEAD | PKT_PDU_TAIL)
95 
96 enum PseudoPacketType
97 {
98     PSEUDO_PKT_IP,
99     PSEUDO_PKT_TCP,
100     PSEUDO_PKT_USER,
101     PSEUDO_PKT_DCE_SEG,
102     PSEUDO_PKT_DCE_FRAG,
103     PSEUDO_PKT_SMB_SEG,
104     PSEUDO_PKT_SMB_TRANS,
105     PSEUDO_PKT_MAX
106 };
107 
108 constexpr int32_t MAX_PORTS = 65536;
109 constexpr uint16_t NUM_IP_PROTOS = 256;
110 constexpr uint8_t TCP_OPTLENMAX = 40; /* (((2^4) - 1) * 4  - TCP_HEADER_LEN) */
111 constexpr uint8_t DEFAULT_LAYERMAX = 40;
112 
113 // Packet is an abstraction describing a unit of work.  it may define a
114 // wire packet or it may define a cooked packet.  the latter contains
115 // payload data only, no headers.
116 struct SO_PUBLIC Packet
117 {
118     Packet(bool packet_data = true);
119     ~Packet();
120 
121     Packet(const Packet&) = delete;
122     Packet& operator=(const Packet&) = delete;
123 
124     Flow* flow;   /* for session tracking */
125     Endianness* endianness;
126     Obfuscator* obfuscator;
127 
128     uint32_t packet_flags;      /* special flags for the packet */
129     uint32_t xtradata_mask;
130     uint32_t proto_bits;        /* protocols contained within this packet */
131 
132     uint16_t alt_dsize;         /* size for detection (iff PKT_DETECT_LIMIT) */
133 
134     uint8_t num_layers;         /* index into layers for next encap */
135     // FIXIT-M Consider moving ip_proto_next below `pkth`.
136     IpProtocol ip_proto_next;      /* the protocol ID after IP and all IP6 extension */
137     bool disable_inspect;
138     mutable FilteringState filtering_state;
139 
140     // nothing after this point is zeroed by reset() ...
141     IpsContext* context;
142     Active* active;
143     Active* active_inst;
144     ActiveAction** action;
145     ActiveAction* action_inst;
146 
147     DAQ_Msg_h daq_msg;              // DAQ message this packet came from
148     SFDAQInstance* daq_instance;    // DAQ instance the message came from
149 
150     // Everything beyond this point is set by PacketManager::decode()
151     const DAQ_PktHdr_t* pkth;   // packet meta data
152     const uint8_t* pkt;         // raw packet data
153     uint32_t pktlen;            // raw packet data length
154 
155     // These are both set before PacketManager::decode() returns
156     const uint8_t* data;        /* packet payload pointer */
157     uint16_t dsize;             /* packet payload size */
158 
159     DecodeData ptrs; // convenience pointers used throughout Snort++
160     Layer* layers;    /* decoded encapsulations */
161 
162     PseudoPacketType pseudo_type;    // valid only when PKT_PSEUDO is set
163     uint32_t iplist_id;
164 
165     uint32_t user_inspection_policy_id;
166     uint32_t user_ips_policy_id;
167     uint32_t user_network_policy_id;
168 
169     uint8_t vlan_idx;
170     uint8_t ts_packet_flags; // FIXIT-M packet flags should always be thread safe
171 
172     // IP_MAXPACKET is the minimum allowable max_dsize
173     // there is no requirement that all data fit into an IP datagram
174     // but we do require that an IP datagram fit into Packet space
175     // we can increase beyond this if needed
176     static const uint32_t max_dsize = IP_MAXPACKET;
177 
178     /*  Boolean functions - general information about this packet */
is_ethPacket179     bool is_eth() const
180     { return ((proto_bits & PROTO_BIT__ETH) != 0); }
181 
has_ipPacket182     bool has_ip() const
183     { return ptrs.ip_api.is_ip(); }
184 
is_ip4Packet185     bool is_ip4() const
186     { return ptrs.ip_api.is_ip4(); }
187 
is_ip6Packet188     bool is_ip6() const
189     { return ptrs.ip_api.is_ip6(); }
190 
is_ipPacket191     bool is_ip() const
192     { return ptrs.get_pkt_type() == PktType::IP; }
193 
is_tcpPacket194     bool is_tcp() const
195     { return ptrs.get_pkt_type() == PktType::TCP; }
196 
is_udpPacket197     bool is_udp() const
198     { return ptrs.get_pkt_type() == PktType::UDP; }
199 
is_icmpPacket200     bool is_icmp() const
201     { return ptrs.get_pkt_type() == PktType::ICMP; }
202 
is_dataPacket203     bool is_data() const
204     { return (ptrs.get_pkt_type() == PktType::PDU) or (ptrs.get_pkt_type() == PktType::FILE); }
205 
is_cookedPacket206     bool is_cooked() const
207     { return ((packet_flags & PKT_PSEUDO) != 0); }
208 
is_fragmentPacket209     bool is_fragment() const
210     { return ptrs.decode_flags & DECODE_FRAG; }
211 
is_udp_tunneledPacket212     bool is_udp_tunneled() const
213     {
214         if (proto_bits & PROTO_BIT__UDP_TUNNELED)
215         {
216             assert(ptrs.udph);
217             return true;
218         }
219 
220         return false;
221     }
222 
has_ip_hdrPacket223     bool has_ip_hdr() const
224     { return ((proto_bits & PROTO_BIT__ANY_IP) != 0); }
225 
has_tcp_dataPacket226     bool has_tcp_data() const
227     { return (proto_bits & PROTO_BIT__TCP) and data and dsize; }
228 
has_udp_dataPacket229     bool has_udp_data() const
230     { return (proto_bits & PROTO_BIT__UDP) and data and dsize; }
231 
232     /* Get general, non-boolean information */
typePacket233     PktType type() const
234     { return ptrs.get_pkt_type(); } // defined in codec.h
235 
set_detect_limitPacket236     void set_detect_limit(uint16_t n)
237     {
238         alt_dsize = n;
239         packet_flags |= PKT_DETECT_LIMIT;
240     }
241 
get_detect_limitPacket242     uint16_t get_detect_limit()
243     { return (packet_flags & PKT_DETECT_LIMIT) ? alt_dsize : dsize; }
244 
245     const char* get_type() const;
246     const char* get_pseudo_type() const;
247 
248     /* the ip_api return the protocol_ID of the protocol directly after the
249      * innermost IP layer.  However, especially in IPv6, the next protocol
250      * can frequently be an IP extension.  Therefore, this function
251      * return the protocol ID of the first protocol after all the
252      * IP layers.  For instance, if the stack is
253      *     eth::ip4::udp::teredo::ip6::hop_opts::ipv6_routing::tcp
254      * this function return 6 == IPPROTO_TCP == IPPROTO_ID_TCP
255      */
get_ip_proto_nextPacket256     IpProtocol get_ip_proto_next() const
257     { return ip_proto_next; }
258 
259     /* Similar to above. However, this function
260      * can be called in a loop to get all of the ip_proto's.
261      * NOTE: Will only return protocols of validly decoded layers.
262      *
263      * PARAMS:
264      *          lyr - zero based layer from which to start searching inward.
265      *                  will always point to the layer after an IP header or
266      *                  IPv6 extension.
267      *          proto - the ip_proto (read above) for the next, outermost IP layer
268      * EXAMPLE:
269      *
270      * uint8_t ip_proto;
271      * int lyr = 0
272      * while ( ip_proto_next(lyr, ip_proto))
273      * {
274      *    ....
275      * }
276      */
277     bool get_ip_proto_next(uint8_t& lyr, IpProtocol& proto) const;
278 
279     void reset();
280     void release_helpers();
281 
is_from_clientPacket282     bool is_from_client() const
283     { return (packet_flags & PKT_FROM_CLIENT) != 0; }
284 
is_from_serverPacket285     bool is_from_server() const
286     { return (packet_flags & PKT_FROM_SERVER) != 0; }
287 
is_from_client_originallyPacket288     bool is_from_client_originally() const
289     { return (!flow || flow->flags.client_initiated) ? is_from_client() : is_from_server(); }
290 
is_from_server_originallyPacket291     bool is_from_server_originally() const
292     { return (!flow || flow->flags.client_initiated) ? is_from_server() : is_from_client(); }
293 
294     bool is_from_application_client() const;
295 
296     bool is_from_application_server() const;
297 
is_full_pduPacket298     bool is_full_pdu() const
299     { return (packet_flags & PKT_PDU_FULL) == PKT_PDU_FULL; }
300 
is_pdu_startPacket301     bool is_pdu_start() const
302     { return (packet_flags & PKT_PDU_HEAD) != 0; }
303 
has_paf_payloadPacket304     bool has_paf_payload() const
305     { return (packet_flags & PKT_REBUILT_STREAM) or is_full_pdu(); }
306 
is_rebuiltPacket307     bool is_rebuilt() const
308     { return (packet_flags & (PKT_REBUILT_STREAM|PKT_REBUILT_FRAG)) != 0; }
309 
is_defragPacket310     bool is_defrag() const
311     { return (packet_flags & PKT_REBUILT_FRAG) != 0; }
312 
is_retryPacket313     bool is_retry() const
314     { return (packet_flags & PKT_RETRY) != 0; }
315 
is_offloadedPacket316     bool is_offloaded() const
317     { return (ts_packet_flags & PKT_TS_OFFLOADED) != 0; }
318 
set_offloadedPacket319     void set_offloaded()
320     { ts_packet_flags |= PKT_TS_OFFLOADED; }
321 
clear_offloadedPacket322     void clear_offloaded()
323     { ts_packet_flags &= (~PKT_TS_OFFLOADED); }
324 
has_parentPacket325     bool has_parent() const
326     { return (packet_flags & PKT_HAS_PARENT) != 0; }
327 
was_setPacket328     bool was_set() const
329     { return (packet_flags & PKT_WAS_SET) != 0; }
330 
331     bool is_detection_enabled(bool to_server);
332 
is_inter_group_flowPacket333     bool is_inter_group_flow() const
334     { return (pkth->flags & DAQ_PKT_FLAG_SIGNIFICANT_GROUPS) != 0; }
335 
336     bool test_session_flags(uint32_t);
337 
338     SnortProtocolId get_snort_protocol_id();
339 
set_snort_protocol_idPacket340     void set_snort_protocol_id(SnortProtocolId proto_id)
341     {
342         assert( ptrs.get_pkt_type() != PktType::PDU);
343 
344         if ( flow )
345             flow->ssn_state.snort_protocol_id = proto_id;
346     }
347 
348     uint16_t get_flow_vlan_id() const;
349     uint32_t get_flow_geneve_vni() const;
350 
get_ingress_groupPacket351     int16_t get_ingress_group() const
352     {
353         if (is_inter_group_flow())
354             return pkth->ingress_group;
355 
356         return DAQ_PKTHDR_UNKNOWN;
357     }
358 
get_egress_groupPacket359     int16_t get_egress_group() const
360     {
361         if (is_inter_group_flow())
362             return pkth->egress_group;
363 
364         return DAQ_PKTHDR_UNKNOWN;
365     }
366 
367 private:
368     bool allocated;
369 };
370 
371 /* Macros to deal with sequence numbers - p810 TCP Illustrated vol 2 */
372 #define SEQ_LT(a,b)  ((int)((a) - (b)) <  0)
373 #define SEQ_LEQ(a,b) ((int)((a) - (b)) <= 0)
374 #define SEQ_GT(a,b)  ((int)((a) - (b)) >  0)
375 #define SEQ_GEQ(a,b) ((int)((a) - (b)) >= 0)
376 #define SEQ_EQ(a,b)  ((int)((a) - (b)) == 0)
377 
378 #define BIT(i) (0x1 << ((i)-1))
379 
SetExtraData(Packet * p,const uint32_t xid)380 inline void SetExtraData(Packet* p, const uint32_t xid) { p->xtradata_mask |= BIT(xid); }
381 
extract_16bits(const uint8_t * const p)382 inline uint16_t extract_16bits(const uint8_t* const p)
383 { return ntohs(*(const uint16_t*)(p)); }
384 
extract_32bits(const uint8_t * p)385 inline uint32_t extract_32bits(const uint8_t* p)
386 {
387     assert(p);
388 
389     return ntohl(*(const uint32_t*)p);
390 }
391 
alignedNtohs(const uint16_t * ptr)392 inline uint16_t alignedNtohs(const uint16_t* ptr)
393 {
394     uint16_t value;
395 
396     if (ptr == nullptr)
397         return 0;
398 
399     value = *ptr;
400 
401 #ifdef WORDS_BIGENDIAN
402     return ((value & 0xff00) >> 8) | ((value & 0x00ff) << 8);
403 #else
404     return value;
405 #endif
406 }
407 
alignedNtohl(const uint32_t * ptr)408 inline uint32_t alignedNtohl(const uint32_t* ptr)
409 {
410     uint32_t value;
411 
412     if (ptr == nullptr)
413         return 0;
414 
415     value = *ptr;
416 
417 #ifdef WORDS_BIGENDIAN
418     return ((value & 0xff000000) >> 24) | ((value & 0x00ff0000) >> 8)  |
419            ((value & 0x0000ff00) << 8)  | ((value & 0x000000ff) << 24);
420 #else
421     return value;
422 #endif
423 }
424 
alignedNtohq(const uint64_t * ptr)425 inline uint64_t alignedNtohq(const uint64_t* ptr)
426 {
427     uint64_t value;
428 
429     if (ptr == nullptr)
430         return 0;
431 
432     value = *ptr;
433 
434 #ifdef WORDS_BIGENDIAN
435     return ((value & 0xff00000000000000) >> 56) | ((value & 0x00ff000000000000) >> 40) |
436            ((value & 0x0000ff0000000000) >> 24) | ((value & 0x000000ff00000000) >> 8)  |
437            ((value & 0x00000000ff000000) << 8)  | ((value & 0x0000000000ff0000) << 24) |
438            ((value & 0x000000000000ff00) << 40) | ((value & 0x00000000000000ff) << 56);
439 #else
440     return value;
441 #endif
442 }
443 }
444 #endif
445 
446