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.cc author Josh Rosenbaum <jrosenba@cisco.com>
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include "packet.h"
25 
26 #include "detection/ips_context.h"
27 #include "flow/expect_cache.h"
28 #include "framework/endianness.h"
29 #include "log/obfuscator.h"
30 #include "packet_io/active.h"
31 #include "managers/codec_manager.h"
32 
33 #include "packet_manager.h"
34 #include "vlan.h"
35 #include "geneve.h"
36 
37 namespace snort
38 {
Packet(bool packet_data)39 Packet::Packet(bool packet_data)
40 {
41     layers = new Layer[CodecManager::get_max_layers()];
42     allocated = packet_data;
43 
44     if (!packet_data)
45     {
46         pkt = nullptr;
47         pkth = nullptr;
48     }
49     else
50     {
51         pkth = new DAQ_PktHdr_t();
52         pkt = new uint8_t[Codec::PKT_MAX];
53     }
54 
55     obfuscator = nullptr;
56     endianness = nullptr;
57     active_inst = new Active();
58     action_inst = nullptr;
59     reset();
60 }
61 
~Packet()62 Packet::~Packet()
63 {
64     release_helpers();
65 
66     if (allocated)
67     {
68         delete pkth;
69         delete[] pkt;
70     }
71     delete active_inst;
72     delete[] layers;
73 }
74 
reset()75 void Packet::reset()
76 {
77     flow = nullptr;
78     packet_flags = 0;
79     ts_packet_flags = 0;
80     xtradata_mask = 0;
81     proto_bits = 0;
82     alt_dsize = 0;
83     num_layers = 0;
84     ip_proto_next = IpProtocol::PROTO_NOT_SET;
85     disable_inspect = false;
86     ExpectFlow::reset_expect_flows();
87 
88     release_helpers();
89     ptrs.reset();
90 
91     iplist_id = 0;
92     user_inspection_policy_id = 0;
93     user_ips_policy_id = 0;
94     user_network_policy_id = 0;
95     vlan_idx = 0;
96     filtering_state.clear();
97 }
98 
release_helpers()99 void Packet::release_helpers()
100 {
101     if ( obfuscator )
102     {
103         delete obfuscator;
104         obfuscator = nullptr;
105     }
106 
107     if ( endianness )
108     {
109         delete endianness;
110         endianness = nullptr;
111     }
112 }
113 
get_ip_proto_next(uint8_t & lyr,IpProtocol & proto) const114 bool Packet::get_ip_proto_next(uint8_t& lyr, IpProtocol& proto) const
115 {
116     if (lyr > num_layers)
117         return false;
118 
119     while (lyr < num_layers)
120     {
121         switch (layers[lyr].prot_id)
122         {
123         case ProtocolId::IPV6:
124         case ProtocolId::ETHERTYPE_IPV6:
125             // move past this IP layer and any IPv6 extensions.
126             while ( ((lyr + 1) < num_layers) && is_ip6_extension(layers[lyr+1].prot_id) )
127                 ++lyr;
128 
129             if ( (layers[lyr].prot_id == ProtocolId::IPV6) || (layers[lyr].prot_id ==
130                 ProtocolId::ETHERTYPE_IPV6) )
131                 proto =  reinterpret_cast<const ip::IP6Hdr*>(layers[lyr++].start)->next();
132             else
133                 proto =  reinterpret_cast<const ip::IP6Extension*>(layers[lyr++].start)->ip6e_nxt;
134 
135             return true;
136 
137         case ProtocolId::ETHERTYPE_IPV4:
138         case ProtocolId::IPIP:
139             proto = reinterpret_cast<const ip::IP4Hdr*>(layers[lyr++].start)->proto();
140             return true;
141 
142         default:
143             ++lyr;
144         }
145     }
146 
147     return false;
148 }
149 
get_type() const150 const char* Packet::get_type() const
151 {
152     switch ( ptrs.get_pkt_type() )
153     {
154     case PktType::IP:
155         return "IP";
156 
157     case PktType::ICMP:
158         return "ICMP";
159 
160     case PktType::TCP:
161         return "TCP";
162 
163     case PktType::UDP:
164         return "UDP";
165 
166     case PktType::PDU:
167     case PktType::FILE:
168         if ( proto_bits & PROTO_BIT__TCP )
169             return "TCP";
170 
171         if ( proto_bits & PROTO_BIT__UDP )
172             return "UDP";
173 
174         assert(false);
175         return "Error";
176 
177     case PktType::NONE:
178         if ( proto_bits & PROTO_BIT__ARP )
179             return "ARP";
180 
181         if ( num_layers > 0 )
182             return PacketManager::get_proto_name(layers[num_layers-1].prot_id);
183 
184         return "None";
185 
186     default:
187         break;
188     }
189     assert(false);
190     return "Error";
191 }
192 
get_pseudo_type() const193 const char* Packet::get_pseudo_type() const
194 {
195     if ( !(packet_flags & PKT_PSEUDO) )
196         return "raw";
197 
198     switch ( pseudo_type )
199     {
200     case PSEUDO_PKT_IP:
201         return "stream_ip";
202 
203     case PSEUDO_PKT_TCP:
204         return "stream_tcp";
205 
206     case PSEUDO_PKT_USER:
207         return "stream_user";
208 
209     case PSEUDO_PKT_DCE_SEG:
210         return "dce2_rpc_deseg";
211 
212     case PSEUDO_PKT_DCE_FRAG:
213         return "dce2_rpc_defrag";
214 
215     case PSEUDO_PKT_SMB_SEG:
216         return "dce2_smb_deseg";
217 
218     case PSEUDO_PKT_SMB_TRANS:
219         return "dce2_smb_transact";
220 
221     default: break;
222     }
223     return "other";
224 }
225 
226 // Things that are set prior to PDU creation and used after PDU creation
get_session_flags(const Packet & p)227 static inline uint32_t get_session_flags(const Packet& p)
228 {
229     if ( p.ptrs.get_pkt_type() == PktType::PDU )
230         return p.context->get_session_flags();
231 
232     return p.flow ? p.flow->get_session_flags() : 0;
233 }
234 
is_detection_enabled(bool to_server)235 bool Packet::is_detection_enabled(bool to_server)
236 {
237     uint32_t session_flags = get_session_flags(*this);
238 
239     if ( to_server )
240         return !(session_flags & SSNFLAG_NO_DETECT_TO_SERVER);
241 
242     return !(session_flags & SSNFLAG_NO_DETECT_TO_CLIENT);
243 }
244 
test_session_flags(uint32_t flags)245 bool Packet::test_session_flags(uint32_t flags)
246 { return (get_session_flags(*this) & flags) != 0; }
247 
get_snort_protocol_id()248 SnortProtocolId Packet::get_snort_protocol_id()
249 {
250     if ( ptrs.get_pkt_type() == PktType::PDU )
251         return context->get_snort_protocol_id();
252 
253     return flow ? flow->ssn_state.snort_protocol_id : UNKNOWN_PROTOCOL_ID;
254 }
255 
get_flow_vlan_id() const256 uint16_t Packet::get_flow_vlan_id() const
257 {
258     uint16_t vid = 0;
259 
260     if (flow)
261         vid = flow->key->vlan_tag;
262     else if ( !context->conf->get_vlan_agnostic() and (proto_bits & PROTO_BIT__VLAN) )
263         vid = layer::get_vlan_layer(this)->vid();
264 
265     return vid;
266 }
267 
get_flow_geneve_vni() const268 uint32_t Packet::get_flow_geneve_vni() const
269 {
270     uint32_t vni = 0;
271 
272     if (proto_bits & PROTO_BIT__GENEVE)
273         vni = layer::get_geneve_layer(this)->vni();
274 
275     return vni;
276 }
277 
is_from_application_client() const278 bool Packet::is_from_application_client() const
279 {
280     if (flow)
281         return flow->flags.app_direction_swapped ? is_from_server() : is_from_client();
282     else
283         return is_from_client();
284 }
285 
is_from_application_server() const286 bool Packet::is_from_application_server() const
287 {
288     if (flow)
289         return flow->flags.app_direction_swapped ? is_from_client() : is_from_server();
290     else
291         return is_from_server();
292 }
293 
294 } // namespace snort
295 
296