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_manager.cc author Josh Rosenbaum <jrosenba@cisco.com>
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "packet_manager.h"
25
26 #include <daq.h>
27 #include <mutex>
28
29 #include "codecs/codec_module.h"
30 #include "codecs/ip/checksum.h"
31 #include "detection/detection_engine.h"
32 #include "log/text_log.h"
33 #include "main/snort_config.h"
34 #include "main/snort_debug.h"
35 #include "packet_io/active.h"
36 #include "packet_io/sfdaq.h"
37 #include "profiler/profiler_defs.h"
38 #include "stream/stream.h"
39
40 #include "eth.h"
41 #include "icmp4.h"
42 #include "icmp6.h"
43
44 using namespace snort;
45
46 THREAD_LOCAL ProfileStats decodePerfStats;
47
48 // Decoding statistics
49
50 // this may be my longer member declaration ... ever
51 THREAD_LOCAL std::array<PegCount,PacketManager::stat_offset +
52 CodecManager::s_protocols.size()> PacketManager::s_stats {
53 { 0 }
54 };
55
56 //PacketManager::s_stats{{0}};
57 std::array<PegCount, PacketManager::s_stats.size()> PacketManager::g_stats;
58
59 // names which will be printed for the first three statistics
60 // in s_stats/g_stats
61 const std::array<const char*, PacketManager::stat_offset> PacketManager::stat_names =
62 {
63 {
64 "total",
65 "other",
66 "discards",
67 "depth_exceeded"
68 }
69 };
70
71 // Encoder Foo
72 static THREAD_LOCAL std::array<uint8_t, Codec::PKT_MAX>* s_pkt;
73
thread_init()74 void PacketManager::thread_init()
75 {
76 s_pkt = new std::array<uint8_t, Codec::PKT_MAX>{ {0} };
77 }
78
thread_term()79 void PacketManager::thread_term()
80 {
81 delete s_pkt;
82 }
83
84 //-------------------------------------------------------------------------
85 // Private helper functions
86 //-------------------------------------------------------------------------
87
push_layer(Packet * p,CodecData & codec_data,ProtocolId prot_id,const uint8_t * hdr_start,uint32_t len)88 inline bool PacketManager::push_layer(Packet* p, CodecData& codec_data, ProtocolId prot_id,
89 const uint8_t* hdr_start, uint32_t len)
90 {
91 if ( p->num_layers == CodecManager::get_max_layers() )
92 {
93 if (!(codec_data.codec_flags & CODEC_LAYERS_EXCEEDED))
94 {
95 codec_data.codec_flags |= CODEC_LAYERS_EXCEEDED;
96 DetectionEngine::queue_event(GID_DECODE, DECODE_TOO_MANY_LAYERS);
97 s_stats[depth_exceeded]++;
98 }
99 return false;
100 }
101
102 Layer& lyr = p->layers[p->num_layers++];
103 lyr.prot_id = prot_id;
104 lyr.start = hdr_start;
105 lyr.length = (uint16_t)len;
106 // lyr.invalid_bits = p->byte_skip; -- currently unused
107
108 return true;
109 }
110
get_layer_codec(const Layer & lyr,int idx)111 inline Codec* PacketManager::get_layer_codec(const Layer& lyr, int idx)
112 {
113 ProtocolIndex mapped_prot;
114 // prot_id == ProtocolId::FINISHED_DECODE is a special case for root codecs not registering a protocol ID
115 if (idx == 0 && (lyr.prot_id == CodecManager::grinder_id || lyr.prot_id == ProtocolId::FINISHED_DECODE))
116 mapped_prot = CodecManager::grinder;
117 else
118 mapped_prot = CodecManager::s_proto_map[to_utype(lyr.prot_id)];
119 return CodecManager::s_protocols[mapped_prot];
120 }
121
pop_teredo(Packet * p,RawData & raw)122 void PacketManager::pop_teredo(Packet* p, RawData& raw)
123 {
124 p->proto_bits &= ~PROTO_BIT__TEREDO;
125 if ( p->context->conf->tunnel_bypass_enabled(TUNNEL_TEREDO) )
126 p->active->clear_tunnel_bypass();
127
128 const ProtocolIndex mapped_prot = CodecManager::s_proto_map[to_utype(ProtocolId::TEREDO)];
129 s_stats[mapped_prot + stat_offset]--;
130 p->num_layers--;
131
132 const Layer& lyr = p->layers[p->num_layers];
133 const uint16_t lyr_len = raw.data - lyr.start;
134 raw.data = lyr.start;
135 raw.len += lyr_len;
136 }
137
handle_decode_failure(Packet * p,RawData & raw,const CodecData & codec_data,const DecodeData & unsure_encap_ptrs,ProtocolId prev_prot_id)138 void PacketManager::handle_decode_failure(Packet* p, RawData& raw, const CodecData& codec_data,
139 const DecodeData& unsure_encap_ptrs, ProtocolId prev_prot_id)
140 {
141 if (codec_data.codec_flags & CODEC_UNSURE_ENCAP)
142 {
143 p->ptrs = unsure_encap_ptrs;
144
145 switch (p->layers[p->num_layers - 1].prot_id)
146 {
147 case ProtocolId::ESP:
148 // Hardcoding ESP because we trust iff the layer
149 // immediately preceding the fail is ESP.
150 p->ptrs.decode_flags |= DECODE_PKT_TRUST;
151 break;
152
153 case ProtocolId::TEREDO:
154 // if we just decoded teredo and the next
155 // layer fails, we made a mistake. Therefore,
156 // remove this bit.
157 pop_teredo(p, raw);
158 break;
159 default:
160 break;
161 }
162 return;
163 }
164
165 if ( (p->num_layers > 0) && (p->layers[p->num_layers - 1].prot_id == ProtocolId::TEREDO) &&
166 (prev_prot_id == ProtocolId::IPV6) )
167 {
168 pop_teredo(p, raw);
169 }
170
171 // if the codec exists, it failed
172 if (CodecManager::s_proto_map[to_utype(prev_prot_id)])
173 {
174 s_stats[discards]++;
175 }
176 else
177 {
178 s_stats[other_codecs]++;
179
180 if ( (to_utype(ProtocolId::MIN_UNASSIGNED_IP_PROTO) <= to_utype(prev_prot_id)) &&
181 (to_utype(prev_prot_id) <= std::numeric_limits<uint8_t>::max()) )
182 {
183 DetectionEngine::queue_event(GID_DECODE, DECODE_IP_UNASSIGNED_PROTO);
184 }
185 }
186 }
187
payload_offset_from_daq_mismatch(const uint8_t * pkt,const RawData & raw)188 static inline bool payload_offset_from_daq_mismatch(const uint8_t* pkt, const RawData& raw)
189 {
190 const DAQ_PktDecodeData_t* pdd =
191 (const DAQ_PktDecodeData_t*) daq_msg_get_meta(raw.daq_msg, DAQ_PKT_META_DECODE_DATA);
192 if ( !pdd || (pdd->payload_offset == DAQ_PKT_DECODE_OFFSET_INVALID) )
193 return false;
194 // compare payload offset from DAQ with decoded data offset
195 if ( raw.data - pkt != pdd->payload_offset )
196 return true;
197 return false;
198 }
199
200 //-------------------------------------------------------------------------
201 // Initialization and setup
202 //-------------------------------------------------------------------------
203
204 // Assertions required for this code to work
205
206 // Look below inside main decode() loop for these static_asserts
207 static_assert(CODEC_ENCAP_LAYER == (CODEC_UNSURE_ENCAP | CODEC_SAVE_LAYER),
208 "If this is an encapsulated layer, you must also set UNSURE_ENCAP"
209 " and SAVE_LAYER");
210
211 //-------------------------------------------------------------------------
212 // Encode/Decode functions
213 //-------------------------------------------------------------------------
decode(Packet * p,const DAQ_PktHdr_t * pkthdr,const uint8_t * pkt,uint32_t pktlen,bool cooked,bool retry)214 void PacketManager::decode(
215 Packet* p, const DAQ_PktHdr_t* pkthdr, const uint8_t* pkt, uint32_t pktlen, bool cooked, bool retry)
216 {
217 Profile profile(decodePerfStats);
218
219 DecodeData unsure_encap_ptrs;
220
221 ProtocolIndex mapped_prot = CodecManager::grinder;
222 ProtocolId prev_prot_id = CodecManager::grinder_id;
223
224 RawData raw(p->daq_msg, pkt, pktlen);
225 CodecData codec_data(p->context->conf, ProtocolId::FINISHED_DECODE);
226
227 if (cooked)
228 codec_data.codec_flags |= CODEC_STREAM_REBUILT;
229
230 // initialize all Packet information
231 p->reset();
232 p->pkth = pkthdr;
233 p->pkt = pkt;
234 p->pktlen = pktlen;
235 if (retry)
236 p->packet_flags |= PKT_RETRY;
237 layer::set_packet_pointer(p);
238
239 s_stats[total_processed]++;
240
241 // loop until the protocol id is no longer valid
242 while (CodecManager::s_protocols[mapped_prot]->decode(raw, codec_data, p->ptrs))
243 {
244 debug_logf(decode_trace, nullptr,
245 "Codec %s (0x%0*hx) starts at %u, length is %hu\n",
246 CodecManager::s_protocols[mapped_prot]->get_name(),
247 (static_cast<uint16_t>(prev_prot_id) < 0xFF) ? 2 : 4,
248 static_cast<uint16_t>(prev_prot_id),
249 pktlen - raw.len, codec_data.lyr_len);
250
251 if (codec_data.codec_flags & CODEC_COMPOUND)
252 {
253 for (int idx = 0; idx < codec_data.compound_layer_cnt; idx++)
254 {
255 CompoundLayer* clyr = &codec_data.compound_layers[idx];
256
257 // If this was an IP layer, stash the next protocol in the Packet for later
258 if (clyr->proto_bits & (PROTO_BIT__IP | PROTO_BIT__IP6_EXT) &&
259 idx + 1 < codec_data.compound_layer_cnt)
260 {
261 CompoundLayer* nclyr = &codec_data.compound_layers[idx + 1];
262 p->ip_proto_next = convert_protocolid_to_ipprotocol(nclyr->layer.prot_id);
263 }
264 p->proto_bits |= clyr->proto_bits;
265
266 // If we have reached the MAX_LAYERS, we keep decoding
267 // but no longer keep track of the layers.
268 if (!push_layer(p, codec_data, clyr->layer.prot_id, clyr->layer.start, clyr->layer.length))
269 continue;
270
271 // Cache the index of the vlan layer for quick access.
272 if (clyr->proto_bits == PROTO_BIT__VLAN)
273 p->vlan_idx = p->num_layers - 1;
274 }
275 codec_data.codec_flags &= ~CODEC_COMPOUND;
276 }
277 else
278 {
279 // If this was an IP layer, stash the next protocol in the Packet for later
280 if (codec_data.proto_bits & (PROTO_BIT__IP | PROTO_BIT__IP6_EXT))
281 {
282 // FIXIT-M refactor when ip_proto's become an array
283 if (p->is_fragment())
284 {
285 if (prev_prot_id == ProtocolId::FRAGMENT)
286 {
287 const ip::IP6Frag* const fragh = reinterpret_cast<const ip::IP6Frag*>(raw.data);
288 p->ip_proto_next = fragh->next();
289 }
290 else
291 p->ip_proto_next = p->ptrs.ip_api.get_ip4h()->proto();
292 }
293 else
294 {
295 if (codec_data.next_prot_id != ProtocolId::FINISHED_DECODE)
296 p->ip_proto_next = convert_protocolid_to_ipprotocol(codec_data.next_prot_id);
297 }
298 }
299
300 // If we have reached the MAX_LAYERS, we keep decoding
301 // but no longer keep track of the layers.
302 if (push_layer(p, codec_data, prev_prot_id, raw.data, codec_data.lyr_len))
303 {
304 // Cache the index of the vlan layer for quick access.
305 if (codec_data.proto_bits == PROTO_BIT__VLAN)
306 p->vlan_idx = p->num_layers - 1;
307 }
308 }
309
310 if (codec_data.tunnel_bypass)
311 {
312 p->active->set_tunnel_bypass();
313 codec_data.tunnel_bypass = false;
314 }
315
316 // Sanity check the next protocol ID is a valid ethertype
317 if (codec_data.codec_flags & CODEC_ETHER_NEXT)
318 {
319 if (codec_data.next_prot_id < ProtocolId::ETHERTYPE_MINIMUM)
320 {
321 DetectionEngine::queue_event(GID_DECODE, DECODE_BAD_ETHER_TYPE);
322 break;
323 }
324 codec_data.codec_flags &= ~CODEC_ETHER_NEXT;
325 }
326
327 /*
328 * We only want the layer immediately following SAVE_LAYER to have the
329 * UNSURE_ENCAP flag set. So, if this is a SAVE_LAYER, zero out the
330 * bit and the next time around, when this is no longer SAVE_LAYER,
331 * we will zero out the UNSURE_ENCAP flag.
332 */
333 if (codec_data.codec_flags & CODEC_SAVE_LAYER)
334 {
335 codec_data.codec_flags &= ~CODEC_SAVE_LAYER;
336 unsure_encap_ptrs = p->ptrs;
337 }
338 else if (codec_data.codec_flags & CODEC_UNSURE_ENCAP)
339 codec_data.codec_flags &= ~CODEC_UNSURE_ENCAP;
340
341 // internal statistics and record keeping
342 s_stats[mapped_prot + stat_offset]++; // add correct decode for previous layer
343 mapped_prot = CodecManager::s_proto_map[to_utype(codec_data.next_prot_id)];
344 prev_prot_id = codec_data.next_prot_id;
345
346 // Shrink the buffer of undecoded data
347 const uint16_t curr_lyr_len = codec_data.lyr_len + codec_data.invalid_bytes;
348 assert(curr_lyr_len <= raw.len);
349 raw.len -= curr_lyr_len;
350 raw.data += curr_lyr_len;
351
352 p->proto_bits |= codec_data.proto_bits;
353
354 // Reset the volatile part of the codec data for the next codec to decode into
355 codec_data.next_prot_id = ProtocolId::FINISHED_DECODE;
356 codec_data.lyr_len = 0;
357 codec_data.invalid_bytes = 0;
358 codec_data.proto_bits = 0;
359 }
360
361 debug_logf(decode_trace, nullptr, "Payload starts at %u, length is %u\n", pktlen - raw.len, raw.len);
362
363 if (p->num_layers > 0)
364 s_stats[mapped_prot + stat_offset]++;
365
366 // if the final protocol ID is not the default codec, a Codec failed
367 if (prev_prot_id != ProtocolId::FINISHED_DECODE || p->num_layers == 0 )
368 handle_decode_failure(p, raw, codec_data, unsure_encap_ptrs, prev_prot_id);
369
370 if (payload_offset_from_daq_mismatch(pkt, raw))
371 p->active->set_tunnel_bypass();
372
373 // set any final Packet fields
374 p->data = raw.data;
375 p->dsize = (uint16_t)raw.len;
376 p->proto_bits |= codec_data.proto_bits;
377
378 if (!p->proto_bits)
379 p->proto_bits = PROTO_BIT__OTHER;
380 }
381
382 //-------------------------------------------------------------------------
383 // encoders operate layer by layer:
384 //-------------------------------------------------------------------------
385
386 //-------------------------------------------------------------------------
387 // encoders:
388 // - raw pkt data only, no need for Packet stuff except to facilitate
389 // encoding
390 // - don't include original options
391 // - inner layer differs from original (eg tcp data segment becomes rst)
392 // - must ensure proper ttl/hop limit for reverse direction
393 //
394 // iterate over decoded layers and encode the response packet. actually
395 // make nested calls. on the way in we setup invariant stuff and as we
396 // unwind the stack we finish up encoding in a more normal fashion (now
397 // the outer layer knows the length of the inner layer, etc.).
398 //
399 // when multiple responses are sent, both forwards and backwards directions,
400 // or multiple ICMP types (unreachable port, host, net), it may be possible
401 // to reuse the 1st encoding and just tweak it. optimization for later
402 // consideration.
403
404 // pci is copied from in to out
405 // * addresses / ports are swapped if !fwd
406 // * options, etc. are stripped
407 // * checksums etc. are set
408 // * if next layer is udp, it is set to icmp unreachable w/udp
409 // * if next layer is tcp, it becomes a tcp rst or tcp fin w/opt data
410 //-------------------------------------------------------------------------
411
GetTTL(const Packet * const p,bool forward)412 static inline uint8_t GetTTL(const Packet* const p, bool forward)
413 {
414 char dir;
415 uint8_t ttl;
416 const bool outer = p->ptrs.ip_api.is_ip();
417
418 if ( !p->flow )
419 return 0;
420
421 if ( p->is_from_client() )
422 dir = forward ? FROM_CLIENT : FROM_SERVER;
423 else
424 dir = forward ? FROM_SERVER : FROM_CLIENT;
425
426 // outermost ip is considered to be outer here,
427 // even if it is the only ip layer ...
428 ttl = Stream::get_flow_ttl(p->flow, dir, outer);
429
430 // if we don't get outer, we use inner
431 if ( 0 == ttl && outer )
432 ttl = Stream::get_flow_ttl(p->flow, dir, false);
433
434 return ttl;
435 }
436
encode(const Packet * p,EncodeFlags flags,uint8_t lyr_start,IpProtocol next_prot,Buffer & buf)437 bool PacketManager::encode(const Packet* p,
438 EncodeFlags flags,
439 uint8_t lyr_start,
440 IpProtocol next_prot,
441 Buffer& buf)
442 {
443 if ( Packet* pe = DetectionEngine::get_encode_packet() )
444 p = pe;
445
446 uint8_t ttl = GetTTL(p, (flags & ENC_FLAG_FWD));
447 if ( ttl )
448 flags |= ENC_FLAG_TTL;
449 else
450 ttl = 0;
451
452 if ( SFDAQ::forwarding_packet(p->pkth) )
453 flags |= ENC_FLAG_INLINE;
454
455 ip::IpApi tmp_api;
456 EncState enc(tmp_api, flags, next_prot, ttl, p->dsize);
457
458 const Layer* const lyrs = p->layers;
459 int8_t outer_layer = lyr_start;
460 int8_t inner_layer = lyr_start;
461
462 // We need the IP layer associated with every protocol
463 // so checksums can be computed.
464 while (layer::set_inner_ip_api(p, tmp_api, inner_layer))
465 {
466 for (int i = outer_layer; i > inner_layer; --i)
467 {
468 const Layer& l = lyrs[i];
469 Codec* cd = get_layer_codec(l, i);
470 if (!cd->encode(l.start, l.length, enc, buf, p->flow))
471 return false;
472 }
473 outer_layer = inner_layer;
474 // inner_layer is set in 'layer::set_inner_ip_api'
475 }
476
477 // Now, we can encode all of the layers between the DLT and
478 // outermost IP layer
479 tmp_api.reset();
480 for (int i = outer_layer; i >= 0; --i)
481 {
482 const Layer& l = lyrs[i];
483 Codec* cd = get_layer_codec(l, i);
484 if (!cd->encode(l.start, l.length, enc, buf, p->flow))
485 return false;
486 }
487
488 return true;
489 }
490
encode_response(TcpResponse type,EncodeFlags flags,const Packet * p,uint32_t & len,const uint8_t * const payload,uint32_t payload_len)491 const uint8_t* PacketManager::encode_response(
492 TcpResponse type, EncodeFlags flags, const Packet* p, uint32_t& len,
493 const uint8_t* const payload, uint32_t payload_len)
494 {
495 Buffer buf(s_pkt->data(), s_pkt->size());
496
497 switch (type)
498 {
499 case TcpResponse::FIN:
500 if (payload && (payload_len > 0))
501 {
502 if (!buf.allocate(payload_len))
503 return nullptr;
504
505 memcpy(buf.data(), payload, payload_len);
506 flags |= ENC_FLAG_PAY;
507 }
508 flags |= ENC_FLAG_FIN;
509 break;
510
511 case TcpResponse::PUSH:
512 if (payload && (payload_len > 0))
513 {
514 if (!buf.allocate(payload_len))
515 return nullptr;
516
517 memcpy(buf.data(), payload, payload_len);
518 flags |= ENC_FLAG_PAY;
519 }
520 flags |= ENC_FLAG_PSH;
521 break;
522
523 case TcpResponse::RST: // No payload, so do nothing.
524 default: // future proof
525 break;
526 }
527
528 // FIXIT-M check flags if we should skip something
529 if (encode(p, flags, p->num_layers-1, IpProtocol::PROTO_NOT_SET, buf))
530 {
531 len = buf.size();
532 return buf.data() + buf.off;
533 }
534
535 len = 0;
536 return nullptr;
537 }
538
encode_reject(UnreachResponse type,EncodeFlags flags,const Packet * p,uint32_t & len)539 const uint8_t* PacketManager::encode_reject(UnreachResponse type,
540 EncodeFlags flags, const Packet* p, uint32_t& len)
541 {
542 Buffer buf(s_pkt->data(), s_pkt->size());
543
544 if (p->is_ip4())
545 {
546 // FIXIT-M check flags if we should skip something
547 const int inner_ip_index = layer::get_inner_ip_lyr_index(p);
548 assert(inner_ip_index >= 0);
549 assert(inner_ip_index+1 < p->num_layers);
550
551 /* Building this packet from the inside out */
552 if (!buf.allocate(icmp::ICMP_UNREACH_DATA_LEN))
553 return nullptr;
554
555 memcpy(buf.data(), p->layers[inner_ip_index+1].start, icmp::ICMP_UNREACH_DATA_LEN);
556
557 const ip::IP4Hdr* const ip4h =
558 reinterpret_cast<const ip::IP4Hdr*>(p->layers[inner_ip_index].start);
559 const uint8_t ip_len = ip4h->hlen();
560
561 if (!buf.allocate(ip_len))
562 return nullptr;
563 memcpy(buf.data(), ip4h, ip_len);
564
565 // If this returns false, we're down pig creek.
566 if (!buf.allocate(sizeof(icmp::Icmp4Base)))
567 return nullptr;
568
569 icmp::Icmp4Base* const icmph = reinterpret_cast<icmp::Icmp4Base*>(buf.data());
570 icmph->type = icmp::IcmpType::DEST_UNREACH;
571 icmph->csum = 0;
572 icmph->opt32 = 0;
573
574 switch (type)
575 {
576 case UnreachResponse::NET:
577 icmph->code = icmp::IcmpCode::NET_UNREACH;
578 break;
579 case UnreachResponse::HOST:
580 icmph->code = icmp::IcmpCode::HOST_UNREACH;
581 break;
582 case UnreachResponse::PORT:
583 icmph->code = icmp::IcmpCode::PORT_UNREACH;
584 break;
585 case UnreachResponse::FWD:
586 icmph->code = icmp::IcmpCode::PKT_FILTERED;
587 break;
588 default: // future proofing
589 icmph->code = icmp::IcmpCode::PORT_UNREACH;
590 }
591
592 icmph->csum = checksum::icmp_cksum((uint16_t*)buf.data(), buf.size());
593
594 if (encode(p, flags, inner_ip_index, IpProtocol::ICMPV4, buf))
595 {
596 len = buf.size();
597 return buf.data() + buf.off;
598 }
599
600 len = 0;
601 return nullptr;
602 }
603 else if (p->is_ip6())
604 {
605 // FIXIT-M check flags if we should skip ip6_options
606 const int inner_ip_index = layer::get_inner_ip_lyr_index(p);
607 assert(inner_ip_index >= 0);
608 assert(inner_ip_index+1 < p->num_layers);
609
610 // FIXIT-L copy up to minimum MTU worth of data
611 // FIXIT-L check if we have the full 8 bytes of data.
612 if (!buf.allocate(icmp::ICMP_UNREACH_DATA_LEN))
613 return nullptr;
614 memcpy(buf.data(), p->layers[inner_ip_index+1].start, icmp::ICMP_UNREACH_DATA_LEN);
615
616 // copy original ip header
617 if (!buf.allocate(ip::IP6_HEADER_LEN))
618 return nullptr;
619 const ip::IP6Hdr* const ip6h = p->ptrs.ip_api.get_ip6h();
620 memcpy(buf.data(), ip6h, ip::IP6_HEADER_LEN);
621
622 if (!buf.allocate(sizeof(icmp::Icmp6Hdr)))
623 return nullptr;
624
625 icmp::Icmp6Hdr* const icmph = reinterpret_cast<icmp::Icmp6Hdr*>(buf.data());
626 icmph->type = icmp::Icmp6Types::DESTINATION_UNREACHABLE;
627 icmph->csum = 0;
628 icmph->opt32 = 0;
629
630 switch (type)
631 {
632 case UnreachResponse::NET:
633 icmph->code = icmp::Icmp6Code::UNREACH_NET;
634 break;
635 case UnreachResponse::HOST:
636 icmph->code = icmp::Icmp6Code::UNREACH_HOST;
637 break;
638 case UnreachResponse::PORT:
639 icmph->code = icmp::Icmp6Code::UNREACH_PORT;
640 break;
641 case UnreachResponse::FWD:
642 icmph->code = icmp::Icmp6Code::UNREACH_FILTER_PROHIB;
643 break;
644 default: // future proofing
645 icmph->code = icmp::Icmp6Code::UNREACH_PORT;
646 }
647
648 checksum::Pseudoheader6 ps6;
649 const int ip_len = buf.size();
650 memcpy(ps6.hdr.sip, ip6h->get_src()->u6_addr8, sizeof(ps6.hdr.sip));
651 memcpy(ps6.hdr.dip, ip6h->get_dst()->u6_addr8, sizeof(ps6.hdr.dip));
652 ps6.hdr.zero = 0;
653 ps6.hdr.protocol = IpProtocol::ICMPV6;
654 ps6.hdr.len = htons((uint16_t)(ip_len));
655
656 icmph->csum = checksum::icmp_cksum((uint16_t*)buf.data(), ip_len, ps6);
657
658 if (encode(p, flags, inner_ip_index, IpProtocol::ICMPV6, buf))
659 {
660 len = buf.size();
661 return buf.data() + buf.off;
662 }
663
664 len = 0;
665 return nullptr;
666 }
667 else
668 {
669 return nullptr;
670 }
671 }
672
init_daq_pkthdr(const Packet * p,Packet * c,const DAQ_PktHdr_t * phdr,uint32_t opaque)673 static void init_daq_pkthdr(
674 const Packet* p, Packet* c, const DAQ_PktHdr_t* phdr, uint32_t opaque)
675 {
676 if ( !phdr )
677 phdr = p->pkth;
678
679 assert(c->pkth == c->context->pkth);
680 DAQ_PktHdr_t* pkth = c->context->pkth;
681 pkth->ingress_index = phdr->ingress_index;
682 pkth->ingress_group = phdr->ingress_group;
683 pkth->egress_index = phdr->egress_index;
684 pkth->egress_group = phdr->egress_group;
685 pkth->flags = phdr->flags;
686 pkth->address_space_id = phdr->address_space_id;
687 pkth->opaque = opaque;
688 }
689
690 //-------------------------------------------------------------------------
691 // formatters:
692 // - these packets undergo detection
693 // - need to set Packet stuff except for frag which calls grinder
694 // - include original options except for frag inner ip
695 // - inner layer header is very similar but payload differs
696 // - original ttl is always used
697 //-------------------------------------------------------------------------
698
format_tcp(EncodeFlags,const Packet * p,Packet * c,PseudoPacketType type,const DAQ_PktHdr_t * phdr,uint32_t opaque)699 int PacketManager::format_tcp(
700 EncodeFlags, const Packet* p, Packet* c, PseudoPacketType type,
701 const DAQ_PktHdr_t* phdr, uint32_t opaque)
702 {
703 uint32_t cflags = c->packet_flags;
704 c->reset();
705 init_daq_pkthdr(p, c, phdr, opaque);
706
707 c->packet_flags = cflags | PKT_PSEUDO;
708 c->pseudo_type = type;
709
710 // cooked packet gets same policy as raw
711 c->user_inspection_policy_id = p->user_inspection_policy_id;
712 c->user_ips_policy_id = p->user_ips_policy_id;
713 c->user_network_policy_id = p->user_network_policy_id;
714 c->ip_proto_next = p->ip_proto_next;
715
716 // setup pkt capture header
717 c->pktlen = 0;
718 assert(c->pkth == c->context->pkth);
719 c->context->pkth->pktlen = 0;
720 c->context->pkth->ts = p->pkth->ts;
721
722 return 0;
723 }
724
encode_format(EncodeFlags f,const Packet * p,Packet * c,PseudoPacketType type,const DAQ_PktHdr_t * phdr,uint32_t opaque)725 int PacketManager::encode_format(
726 EncodeFlags f, const Packet* p, Packet* c, PseudoPacketType type,
727 const DAQ_PktHdr_t* phdr, uint32_t opaque)
728 {
729 bool update_ip4_len = false;
730 uint8_t num_layers;
731
732 if ( f & ENC_FLAG_DEF )
733 {
734 /*
735 * By its definitions, this flag means 'stop before innermost ip4
736 * opts or ip6 frag header'. So, stop after the ip4 layer IP4 will format itself, and now
737 * we ensure that the ip6_frag header is not copied too.
738 */
739
740 if ( p->is_ip6() )
741 {
742 num_layers = layer::get_inner_ip6_frag_index(p);
743 }
744 else
745 {
746 num_layers = layer::get_inner_ip_lyr_index(p) + 1;
747 update_ip4_len = true;
748 }
749 }
750 else if ( f & ENC_FLAG_NET )
751 num_layers = layer::get_inner_ip_lyr_index(p) + 1;
752 else
753 num_layers = p->num_layers;
754
755 if ( num_layers == 0 )
756 return -1;
757
758 init_daq_pkthdr(p, c, phdr, opaque);
759
760 // copy raw packet data to clone
761 Layer* lyr = &p->layers[num_layers - 1];
762 int len = lyr->start - p->pkt + lyr->length;
763 memcpy((void*)c->pkt, p->pkt, len);
764
765 const bool reverse = !(f & ENC_FLAG_FWD);
766
767 // set up and format layers
768 for ( int i = 0; i < num_layers; i++ )
769 {
770 const uint8_t* b = c->pkt + (p->layers[i].start - p->pkt); // == c->pkt + p->layers[i].len
771 lyr = &c->layers[i];
772
773 lyr->prot_id = p->layers[i].prot_id;
774 lyr->length = p->layers[i].length;
775 lyr->start = b;
776
777 // NOTE: this must always go from outer to inner
778 // to ensure a valid ip header
779 Codec* cd = get_layer_codec(*lyr, i);
780 cd->format(reverse, const_cast<uint8_t*>(lyr->start), c->ptrs);
781 }
782
783 if ( update_ip4_len )
784 {
785 lyr = &c->layers[num_layers - 1];
786 ip::IP4Hdr* ip4h = reinterpret_cast<ip::IP4Hdr*>(const_cast<uint8_t*>(lyr->start));
787 lyr->length = ip::IP4_HEADER_LEN;
788 ip4h->set_ip_len(ip::IP4_HEADER_LEN);
789 ip4h->set_hlen(ip::IP4_HEADER_LEN >> 2);
790 }
791
792 // setup payload info
793 c->num_layers = num_layers;
794 c->data = lyr->start + lyr->length;
795 len = c->data - c->pkt;
796
797 // len < ETHERNET_HEADER_LEN + VLAN_HEADER + ETHERNET_MTU
798 assert((unsigned)len < Codec::PKT_MAX - c->max_dsize);
799
800 c->proto_bits = p->proto_bits;
801 c->ip_proto_next = p->ip_proto_next;
802 c->packet_flags |= PKT_PSEUDO;
803 c->pseudo_type = type;
804
805 // cooked packet gets same policy as raw
806 c->user_inspection_policy_id = p->user_inspection_policy_id;
807 c->user_ips_policy_id = p->user_ips_policy_id;
808 c->user_network_policy_id = p->user_network_policy_id;
809
810 // setup pkt capture header
811 c->pktlen = len;
812 assert(c->pkth == c->context->pkth);
813 c->context->pkth->pktlen = len;
814 c->context->pkth->ts = p->pkth->ts;
815
816 layer::set_packet_pointer(c); // ensure we are looking at the new packet
817 return 0;
818 }
819
820 //-------------------------------------------------------------------------
821 // updaters: these functions set length and checksum fields, only needed
822 // when a packet is modified. some packets only have replacements so only
823 // the checksums need to be updated. we always set the length rather than
824 // checking each time if needed.
825 //-------------------------------------------------------------------------
826
add_flag(UpdateFlags & flags,UpdateFlags flag_to_add,const Packet * const p,decltype(Packet::packet_flags)pkt_flag)827 static inline void add_flag(
828 UpdateFlags& flags, UpdateFlags flag_to_add, const Packet* const p,
829 decltype(Packet::packet_flags)pkt_flag) // future proofing.
830 {
831 if ( p->packet_flags & pkt_flag )
832 flags |= flag_to_add;
833 }
834
encode_update(Packet * p)835 void PacketManager::encode_update(Packet* p)
836 {
837 uint32_t len = p->dsize;
838
839 UpdateFlags flags = 0;
840 add_flag(flags, UPD_COOKED, p, PKT_PSEUDO);
841 add_flag(flags, UPD_MODIFIED, p, PKT_MODIFIED);
842 add_flag(flags, UPD_RESIZED, p, PKT_RESIZED);
843 add_flag(flags, UPD_REBUILT_FRAG, p, PKT_REBUILT_FRAG);
844
845 int8_t outer_layer = p->num_layers-1;
846 int8_t inner_layer = p->num_layers-1;
847 const Layer* const lyr = p->layers;
848 ip::IpApi tmp_api;
849
850 // update the rest of the ip layers with the correct IP reference.
851 while (layer::set_inner_ip_api(p, tmp_api, inner_layer))
852 {
853 for (int i = outer_layer; i > inner_layer; --i)
854 {
855 const Layer& l = lyr[i];
856 Codec* cd = get_layer_codec(l, i);
857 cd->update(tmp_api, flags, const_cast<uint8_t*>(l.start), l.length, len);
858 }
859 outer_layer = inner_layer;
860 // inner_layer is set in 'layer::set_inner_ip_api'
861 }
862
863 tmp_api.reset();
864 for (int i = outer_layer; i >= 0; --i)
865 {
866 const Layer& l = lyr[i];
867 ProtocolIndex mapped_prot = CodecManager::s_proto_map[to_utype(l.prot_id)];
868 CodecManager::s_protocols[mapped_prot]->update(
869 tmp_api, flags, const_cast<uint8_t*>(l.start), l.length, len);
870 }
871
872 if ( !(p->packet_flags & PKT_MODIFIED) || (p->packet_flags & PKT_RESIZED) )
873 {
874 p->pktlen = len;
875 // Only attempt to update the DAQ packet header for manufactured (defragged) packets. If
876 // this is the original wire packet, leave the header alone; the drop/inject for resize
877 // will use pktlen from Packet for the injection length.
878 // FIXIT-L there should be a better way to detect that this is manufactured packet
879 if (p->pkth == p->context->pkth)
880 p->context->pkth->pktlen = len;
881 }
882 }
883
884 //-------------------------------------------------------------------------
885 // codec support and statistics
886 //-------------------------------------------------------------------------
887
encode_get_max_payload(const Packet * p)888 uint16_t PacketManager::encode_get_max_payload(const Packet* p)
889 {
890 if ( !p->num_layers )
891 return 0;
892
893 const Layer& l = p->layers[p->num_layers - 1];
894 return ETHERNET_MTU - (l.start - p->layers[0].start) - l.length;
895 }
896
dump_stats()897 void PacketManager::dump_stats()
898 {
899 std::vector<const char*> pkt_names;
900
901 // zero out the default codecs
902 g_stats[stat_offset] = 0;
903 g_stats[CodecManager::s_proto_map[to_utype(ProtocolId::FINISHED_DECODE)] + stat_offset] = 0;
904
905 for (unsigned int i = 0; i < stat_names.size(); i++)
906 pkt_names.emplace_back(stat_names[i]);
907
908 for (int i = 0; CodecManager::s_protocols[i] != nullptr; i++)
909 pkt_names.emplace_back(CodecManager::s_protocols[i]->get_name());
910
911 show_percent_stats((PegCount*)&g_stats, &pkt_names[0],
912 (unsigned int)pkt_names.size(), "codec");
913 }
914
reset_stats()915 void PacketManager::reset_stats()
916 {
917 std::fill(std::begin(g_stats), std::end(g_stats), 0);
918 std::fill(std::begin(s_stats), std::end(s_stats), 0);
919 }
920
accumulate()921 void PacketManager::accumulate()
922 {
923 static std::mutex stats_mutex;
924
925 std::lock_guard<std::mutex> lock(stats_mutex);
926 sum_stats(&g_stats[0], &s_stats[0], s_stats.size());
927
928 // mutex is automatically unlocked
929 }
930
get_proto_name(ProtocolId protocol)931 const char* PacketManager::get_proto_name(ProtocolId protocol)
932 { return CodecManager::s_protocols[CodecManager::s_proto_map[to_utype(protocol)]]->get_name(); }
933
get_proto_name(IpProtocol protocol)934 const char* PacketManager::get_proto_name(IpProtocol protocol)
935 { return CodecManager::s_protocols[CodecManager::s_proto_map[to_utype(protocol)]]->get_name(); }
936
log_protocols(TextLog * const text_log,const Packet * const p)937 void PacketManager::log_protocols(TextLog* const text_log,
938 const Packet* const p)
939 {
940 uint8_t num_layers = p->num_layers;
941 const Layer* const lyr = p->layers;
942
943 if (num_layers != 0)
944 {
945 int i = 0;
946 // Special case for root codecs not registering a protocol ID
947 if (lyr[0].prot_id == CodecManager::grinder_id || lyr[0].prot_id == ProtocolId::FINISHED_DECODE)
948 {
949 Codec* cd = CodecManager::s_protocols[CodecManager::grinder];
950 TextLog_Print(text_log, "%s(DLT): ", cd->get_name());
951 cd->log(text_log, lyr[0].start, lyr[0].length);
952 i++;
953 }
954
955 for (; i < num_layers; i++)
956 {
957 const auto protocol = to_utype(lyr[i].prot_id);
958 const uint8_t codec_offset = CodecManager::s_proto_map[protocol];
959 Codec* cd = CodecManager::s_protocols[codec_offset];
960
961 TextLog_NewLine(text_log);
962 TextLog_Print(text_log, "%s", cd->get_name());
963
964 if (protocol <= 0xFF)
965 TextLog_Print(text_log, "(0x%02x)", protocol);
966 else
967 TextLog_Print(text_log, "(0x%04x)", protocol);
968
969 TextLog_Puts(text_log, ": ");
970 cd->log(text_log, lyr[i].start, lyr[i].length);
971 }
972 }
973 }
974