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 // layer.cc author Josh Rosenbaum <jrosenba@cisco.com>
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "layer.h"
25
26 #include "packet.h"
27
28 namespace snort
29 {
30 namespace layer
31 {
32 static THREAD_LOCAL const Packet* curr_pkt;
33
find_outer_layer(const Layer * lyr,uint8_t num_layers,ProtocolId prot_id)34 static inline const uint8_t* find_outer_layer(const Layer* lyr,
35 uint8_t num_layers,
36 ProtocolId prot_id)
37 {
38 for (int i = 0; i < num_layers; i++)
39 {
40 if (lyr->prot_id == prot_id)
41 return lyr->start;
42 lyr++;
43 }
44 return nullptr;
45 }
46
find_inner_layer(const Layer * lyr,uint8_t num_layers,ProtocolId prot_id)47 static inline const uint8_t* find_inner_layer(const Layer* lyr,
48 uint8_t num_layers,
49 ProtocolId prot_id)
50 {
51 int tmp = num_layers-1;
52 lyr = &lyr[tmp];
53
54 for (int i = tmp; i >= 0; i--)
55 {
56 if (lyr->prot_id == prot_id)
57 return lyr->start;
58 lyr--;
59 }
60 return nullptr;
61 }
62
find_inner_layer(const Layer * lyr,uint8_t num_layers,ProtocolId prot_id1,ProtocolId prot_id2)63 static inline const uint8_t* find_inner_layer(const Layer* lyr,
64 uint8_t num_layers,
65 ProtocolId prot_id1,
66 ProtocolId prot_id2)
67 {
68 int tmp = num_layers-1;
69 lyr = &lyr[tmp];
70
71 for (int i = num_layers - 1; i >= 0; i--)
72 {
73 if (lyr->prot_id == prot_id1 ||
74 lyr->prot_id == prot_id2)
75 return lyr->start;
76 lyr--;
77 }
78 return nullptr;
79 }
80
find_layer(const Layer * lyr,uint8_t num_layers,ProtocolId prot_id1,ProtocolId prot_id2)81 static inline const Layer* find_layer(const Layer* lyr,
82 uint8_t num_layers,
83 ProtocolId prot_id1,
84 ProtocolId prot_id2)
85 {
86 int tmp = num_layers-1;
87 lyr = &lyr[tmp];
88
89 for (int i = num_layers - 1; i >= 0; i--)
90 {
91 if (lyr->prot_id == prot_id1 ||
92 lyr->prot_id == prot_id2)
93 return lyr;
94 lyr--;
95 }
96 return nullptr;
97 }
98
set_packet_pointer(const Packet * const p)99 void set_packet_pointer(const Packet* const p)
100 { curr_pkt = p; }
101
get_inner_layer(const Packet * p,ProtocolId prot_id)102 const uint8_t* get_inner_layer(const Packet* p, ProtocolId prot_id)
103 { return find_inner_layer(p->layers, p->num_layers, prot_id); }
104
get_outer_layer(const Packet * p,ProtocolId prot_id)105 const uint8_t* get_outer_layer(const Packet* p, ProtocolId prot_id)
106 { return find_outer_layer(p->layers, p->num_layers, prot_id); }
107
get_arp_layer(const Packet * const p)108 const arp::EtherARP* get_arp_layer(const Packet* const p)
109 {
110 uint8_t num_layers = p->num_layers;
111 const Layer* lyr = p->layers;
112
113 return reinterpret_cast<const arp::EtherARP*>(
114 find_inner_layer(lyr, num_layers, ProtocolId::ETHERTYPE_ARP,
115 ProtocolId::ETHERTYPE_REVARP));
116 }
117
get_geneve_layer(const Packet * const p)118 const geneve::GeneveHdr* get_geneve_layer(const Packet* const p)
119 {
120 uint8_t num_layers = p->num_layers;
121 const Layer* lyr = p->layers;
122
123 return reinterpret_cast<const geneve::GeneveHdr*>(
124 find_inner_layer(lyr, num_layers, ProtocolId::GENEVE));
125 }
126
get_gre_layer(const Packet * const p)127 const gre::GREHdr* get_gre_layer(const Packet* const p)
128 {
129 uint8_t num_layers = p->num_layers;
130 const Layer* lyr = p->layers;
131
132 return reinterpret_cast<const gre::GREHdr*>(
133 find_inner_layer(lyr, num_layers, ProtocolId::GRE));
134 }
135
get_eapol_layer(const Packet * const p)136 const eapol::EtherEapol* get_eapol_layer(const Packet* const p)
137 {
138 uint8_t num_layers = p->num_layers;
139 const Layer* lyr = p->layers;
140
141 return reinterpret_cast<const eapol::EtherEapol*>(
142 find_inner_layer(lyr, num_layers, ProtocolId::ETHERTYPE_EAPOL));
143 }
144
get_mpls_layer(const Packet * const p)145 const Layer* get_mpls_layer(const Packet* const p)
146 {
147 uint8_t num_layers = p->num_layers;
148 const Layer* lyr = p->layers;
149
150 return find_layer(lyr, num_layers, ProtocolId::ETHERTYPE_MPLS_UNICAST,
151 ProtocolId::ETHERTYPE_MPLS_MULTICAST);
152 }
153
get_vlan_layer(const Packet * const p)154 const vlan::VlanTagHdr* get_vlan_layer(const Packet* const p)
155 {
156 assert( p->proto_bits & PROTO_BIT__VLAN );
157 assert( p->vlan_idx < p->num_layers );
158 const Layer* lyr = p->layers + p->vlan_idx;
159 return reinterpret_cast<const vlan::VlanTagHdr*>(lyr->start);
160 }
161
get_cisco_meta_data_layer(const Packet * const p)162 const cisco_meta_data::CiscoMetaDataHdr* get_cisco_meta_data_layer(const Packet* const p)
163 {
164 assert( p->proto_bits & PROTO_BIT__CISCO_META_DATA );
165
166 const Layer* lyr = find_layer(p->layers, p->num_layers, ProtocolId::ETHERTYPE_CISCO_META,
167 ProtocolId::ETHERTYPE_CISCO_META);
168
169 return reinterpret_cast<const cisco_meta_data::CiscoMetaDataHdr*>(lyr->start);
170 }
171
get_eth_layer(const Packet * const p)172 const eth::EtherHdr* get_eth_layer(const Packet* const p)
173 {
174 uint8_t num_layers = p->num_layers;
175 const Layer* lyr = p->layers;
176
177 // First, search for the inner eth layer (transbridging)
178 const eth::EtherHdr* eh = reinterpret_cast<const eth::EtherHdr*>(
179 find_inner_layer(lyr, num_layers, ProtocolId::ETHERTYPE_TRANS_ETHER_BRIDGING));
180
181 // if no inner eth layer, assume root layer is eth (callers job to confirm)
182 return eh ? eh : reinterpret_cast<const eth::EtherHdr*>(get_root_layer(p));
183 }
184
get_wifi_layer(const Packet * const p)185 const wlan::WifiHdr* get_wifi_layer(const Packet* const p)
186 {
187 uint8_t num_layers = p->num_layers;
188 const Layer* lyr = p->layers;
189
190 return reinterpret_cast<const wlan::WifiHdr*>(
191 find_inner_layer(lyr, num_layers, ProtocolId::ETHERNET_802_11));
192 }
193
get_inner_ip6_frag()194 const ip::IP6Frag* get_inner_ip6_frag()
195 { return get_inner_ip6_frag(curr_pkt); }
196
get_inner_ip6_frag(const Packet * const pkt)197 const ip::IP6Frag* get_inner_ip6_frag(const Packet* const pkt)
198 {
199 // get_ip6h returns null if this is ipv4
200 const ip::IP6Hdr* const ip6h = pkt->ptrs.ip_api.get_ip6h();
201
202 if (ip6h)
203 {
204 const int max_layer = pkt->num_layers-1;
205 const Layer* lyr = &(pkt->layers[max_layer]);
206
207 for (int i = max_layer; i >= 0; i--)
208 {
209 if (lyr->prot_id == ProtocolId::FRAGMENT)
210 return reinterpret_cast<const ip::IP6Frag*>(lyr->start);
211
212 // Only check until current ip6h header
213 if (lyr->start == (const uint8_t*)ip6h)
214 return nullptr;
215
216 lyr--;
217 }
218 }
219
220 return nullptr;
221 }
222
get_inner_ip6_frag_index(const Packet * const pkt)223 int get_inner_ip6_frag_index(const Packet* const pkt)
224 {
225 // get_ip6h returns null if this is ipv4
226 const ip::IP6Hdr* const ip6h = pkt->ptrs.ip_api.get_ip6h();
227
228 if (ip6h && curr_pkt->is_fragment())
229 {
230 const int max_layer = pkt->num_layers-1;
231 const Layer* lyr = &(pkt->layers[max_layer]);
232
233 for (int i = max_layer; i >= 0; i--)
234 {
235 if (lyr->prot_id == ProtocolId::FRAGMENT)
236 return i;
237
238 lyr--;
239 }
240 }
241 return -1;
242 }
243
get_outer_udp_lyr(const Packet * const p)244 const udp::UDPHdr* get_outer_udp_lyr(const Packet* const p)
245 {
246 return reinterpret_cast<const udp::UDPHdr*>(
247 find_outer_layer(p->layers, p->num_layers, ProtocolId::UDP));
248 }
249
get_root_layer(const Packet * const p)250 const uint8_t* get_root_layer(const Packet* const p)
251 {
252 // since token ring is the grinder, its the beginning of the packet.
253 if (p->num_layers > 0)
254 return p->layers[0].start;
255 return nullptr;
256 }
257
get_inner_ip_lyr_index(const Packet * const p)258 int get_inner_ip_lyr_index(const Packet* const p)
259 {
260 const Layer* layers = p->layers;
261
262 for (int i = p->num_layers-1; i >= 0; i--)
263 {
264 switch (layers[i].prot_id)
265 {
266 case ProtocolId::ETHERTYPE_IPV4:
267 case ProtocolId::ETHERTYPE_IPV6:
268 case ProtocolId::IPIP:
269 case ProtocolId::IPV6:
270 return i;
271 default:
272 break;
273 }
274 }
275 return -1;
276 }
277
set_inner_ip_api(const Packet * const p,ip::IpApi & api,int8_t & curr_layer)278 bool set_inner_ip_api(const Packet* const p,
279 ip::IpApi& api,
280 int8_t& curr_layer)
281 {
282 IpProtocol tmp;
283 return set_inner_ip_api(p, api, tmp, curr_layer);
284 }
285
set_inner_ip_api(const Packet * const p,ip::IpApi & api,IpProtocol & next_ip_proto,int8_t & curr_layer)286 bool set_inner_ip_api(const Packet* const p,
287 ip::IpApi& api,
288 IpProtocol& next_ip_proto,
289 int8_t& curr_layer)
290 {
291 if (curr_layer < 0 || curr_layer >= p->num_layers)
292 return false;
293
294 if (is_ip6_extension(p->layers[curr_layer].prot_id))
295 {
296 const ip::IP6Extension* const ip6_ext =
297 reinterpret_cast<const ip::IP6Extension*>(p->layers[curr_layer].start);
298 next_ip_proto = ip6_ext->ip6e_nxt;
299 curr_layer--;
300 }
301
302 do
303 {
304 const Layer& lyr = p->layers[curr_layer];
305
306 switch (lyr.prot_id)
307 {
308 case ProtocolId::ETHERTYPE_IPV4:
309 case ProtocolId::IPIP:
310 {
311 const ip::IP4Hdr* ip4h =
312 reinterpret_cast<const ip::IP4Hdr*>(lyr.start);
313 api.set(ip4h);
314 curr_layer--;
315 return true;
316 }
317
318 case ProtocolId::ETHERTYPE_IPV6:
319 case ProtocolId::IPV6:
320 {
321 const ip::IP6Hdr* ip6h =
322 reinterpret_cast<const ip::IP6Hdr*>(lyr.start);
323 api.set(ip6h);
324 curr_layer--;
325 return true;
326 }
327
328 case ProtocolId::HOPOPTS:
329 case ProtocolId::DSTOPTS:
330 case ProtocolId::ROUTING:
331 case ProtocolId::FRAGMENT:
332 case ProtocolId::AUTH:
333 case ProtocolId::ESP:
334 case ProtocolId::MOBILITY_IPV6:
335 case ProtocolId::NONEXT:
336 break;
337
338 default:
339 if(is_ip_protocol(lyr.prot_id))
340 next_ip_proto = convert_protocolid_to_ipprotocol(lyr.prot_id);
341 }
342 }
343 while (--curr_layer >= 0);
344
345 return false;
346 }
347
set_outer_ip_api(const Packet * const p,ip::IpApi & api,IpProtocol & ip_proto_next,int8_t & curr_layer)348 bool set_outer_ip_api(const Packet* const p,
349 ip::IpApi& api,
350 IpProtocol& ip_proto_next,
351 int8_t& curr_layer)
352 {
353 if (set_outer_ip_api(p, api, curr_layer))
354 {
355 if (api.is_ip6())
356 {
357 const uint8_t num_layers = p->num_layers;
358
359 while (curr_layer < num_layers &&
360 is_ip6_extension(p->layers[curr_layer].prot_id))
361 {
362 curr_layer++;
363 }
364
365 // edge case. Final layer is an IP6 extension.
366 if (curr_layer >= num_layers &&
367 is_ip6_extension(p->layers[curr_layer].prot_id))
368 {
369 const ip::IP6Extension* const ip6_ext =
370 reinterpret_cast<const ip::IP6Extension*>(p->layers[curr_layer-1].start);
371 ip_proto_next = ip6_ext->ip6e_nxt;
372 return true;
373 }
374 }
375
376 ip_proto_next = convert_protocolid_to_ipprotocol(p->layers[curr_layer].prot_id);
377 return true;
378 }
379
380 return false;
381 }
382
set_outer_ip_api(const Packet * const p,ip::IpApi & api,int8_t & curr_layer)383 bool set_outer_ip_api(const Packet* const p,
384 ip::IpApi& api,
385 int8_t& curr_layer)
386 {
387 const uint8_t num_layers = p->num_layers;
388 if (curr_layer < 0 || curr_layer >= num_layers)
389 return false;
390
391 do
392 {
393 const Layer& lyr = p->layers[curr_layer];
394
395 switch (lyr.prot_id)
396 {
397 case ProtocolId::ETHERTYPE_IPV4:
398 case ProtocolId::IPIP:
399 {
400 const ip::IP4Hdr* ip4h =
401 reinterpret_cast<const ip::IP4Hdr*>(lyr.start);
402 api.set(ip4h);
403 curr_layer++;
404 if(curr_layer >= num_layers)
405 return false;
406 return true;
407 }
408 case ProtocolId::ETHERTYPE_IPV6:
409 case ProtocolId::IPV6:
410 {
411 const ip::IP6Hdr* ip6h =
412 reinterpret_cast<const ip::IP6Hdr*>(lyr.start);
413 api.set(ip6h);
414 curr_layer++;
415 if(curr_layer >= num_layers)
416 return false;
417 return true;
418 }
419 default:
420 ; // don't care about this layer if its not IP.
421 }
422 }
423 while (++curr_layer < num_layers);
424
425 return false;
426 }
427
set_api_ip_embed_icmp(const Packet * p,ip::IpApi & api)428 bool set_api_ip_embed_icmp(const Packet* p, ip::IpApi& api)
429 {
430 int num_layers = p->num_layers - 1;
431
432 for (int i = num_layers; i >= 0; --i)
433 {
434 const Layer& lyr = p->layers[i];
435
436 if (lyr.prot_id == ProtocolId::IP_EMBEDDED_IN_ICMP4)
437 {
438 const ip::IP4Hdr* ip4h =
439 reinterpret_cast<const ip::IP4Hdr*>(lyr.start);
440 api.set(ip4h);
441 return true;
442 }
443 else if (lyr.prot_id == ProtocolId::IP_EMBEDDED_IN_ICMP6)
444 {
445 const ip::IP6Hdr* ip6h =
446 reinterpret_cast<const ip::IP6Hdr*>(lyr.start);
447 api.set(ip6h);
448 return true;
449 }
450 }
451
452 api.reset();
453 return false;
454 }
455
get_tcp_embed_icmp(const ip::IpApi & api)456 const tcp::TCPHdr* get_tcp_embed_icmp(const ip::IpApi& api)
457 { return reinterpret_cast<const tcp::TCPHdr*>(api.ip_data()); }
458
get_udp_embed_icmp(const ip::IpApi & api)459 const udp::UDPHdr* get_udp_embed_icmp(const ip::IpApi& api)
460 { return reinterpret_cast<const udp::UDPHdr*>(api.ip_data()); }
461
get_icmp_embed_icmp(const ip::IpApi & api)462 const icmp::ICMPHdr* get_icmp_embed_icmp(const ip::IpApi& api)
463 { return reinterpret_cast<const icmp::ICMPHdr*>(api.ip_data()); }
464 } // namespace layer
465 } // namespace snort
466