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