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