00001 //--------------------------------------------------------------------------
00002 // Copyright (C) 2014-2017 Cisco and/or its affiliates. All rights reserved.
00003 //
00004 // This program is free software; you can redistribute it and/or modify it
00005 // under the terms of the GNU General Public License Version 2 as published
00006 // by the Free Software Foundation. You may not use, modify or distribute
00007 // this program under any other version of the GNU General Public License.
00008 //
00009 // This program is distributed in the hope that it will be useful, but
00010 // WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License along
00015 // with this program; if not, write to the Free Software Foundation, Inc.,
00016 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017 //--------------------------------------------------------------------------
00018 // packet_manager.cc author Josh Rosenbaum <jrosenba@cisco.com>
00019
00020 #ifdef HAVE_CONFIG_H
00021 #include "config.h"
00022 #endif
00023
00024 #include "packet_manager.h"
00025
00026 #include <mutex>
00027
00028 #include "codecs/codec_module.h"
00029 #include "codecs/ip/checksum.h"
00030 #include "detection/detection_engine.h"
00031 #include "log/text_log.h"
00032 #include "main/snort_config.h"
00033 #include "main/snort_debug.h"
00034 #include "packet_io/active.h"
00035 #include "packet_io/sfdaq.h"
00036 #include "profiler/profiler_defs.h"
00037 #include "stream/stream.h"
00038
00039 #include "eth.h"
00040 #include "icmp4.h"
00041 #include "icmp6.h"
00042
00043 THREAD_LOCAL ProfileStats decodePerfStats;
00044
00045 // Decoding statistics
00046
00047 // this may be my longer member declaration ... ever
00048 THREAD_LOCAL std::array<PegCount,PacketManager::stat_offset +
00049 CodecManager::s_protocols.size()> PacketManager::s_stats {
00050 { 0 }
00051 };
00052
00053 //PacketManager::s_stats{{0}};
00054 std::array<PegCount, PacketManager::s_stats.size()> PacketManager::g_stats;
00055
00056 // names which will be printed for the first three statistics
00057 // in s_stats/g_stats
00058 const std::array<const char*, PacketManager::stat_offset> PacketManager::stat_names =
00059 {
00060 {
00061 "total",
00062 "other",
00063 "discards"
00064 }
00065 };
00066
00067 // Encoder Foo
00068 static THREAD_LOCAL PegCount total_rebuilt_pkts = 0;
00069 static THREAD_LOCAL std::array<uint8_t, Codec::PKT_MAX> s_pkt { { 0 } };
00070
00071 //-------------------------------------------------------------------------
00072 // Private helper functions
00073 //-------------------------------------------------------------------------
00074
00075 static inline void push_layer(Packet* p,
00076 ProtocolId prot_id,
00077 const uint8_t* hdr_start,
00078 uint32_t len)
00079 {
00080 // We check to ensure num_layer < MAX_LAYERS before this function call
00081 Layer& lyr = p->layers[p->num_layers++];
00082 lyr.prot_id = prot_id;
00083 lyr.start = hdr_start;
00084 lyr.length = (uint16_t)len;
00085 // lyr.invalid_bits = p->byte_skip; -- currently unused
00086 }
00087
00088 void PacketManager::pop_teredo(Packet* p, RawData& raw)
00089 {
00090 p->proto_bits &= ~PROTO_BIT__TEREDO;
00091 if ( SnortConfig::tunnel_bypass_enabled(TUNNEL_TEREDO) )
00092 Active::clear_tunnel_bypass();
00093
00094 const ProtocolIndex mapped_prot = CodecManager::s_proto_map[to_utype(ProtocolId::TEREDO)];
00095 s_stats[mapped_prot + stat_offset]--;
00096 p->num_layers--;
00097
00098 const Layer& lyr = p->layers[p->num_layers];
00099 const uint16_t lyr_len = raw.data - lyr.start;
00100 raw.data = lyr.start;
00101 raw.len += lyr_len;
00102 }
00103
00104 //-------------------------------------------------------------------------
00105 // Initialization and setup
00106 //-------------------------------------------------------------------------
00107
00108 // Assertions required for this code to work
00109
00110 // Look below inside main decode() loop for these static_asserts
00111 static_assert(CODEC_ENCAP_LAYER == (CODEC_UNSURE_ENCAP | CODEC_SAVE_LAYER),
00112 "If this is an encapsulated layer, you must also set UNSURE_ENCAP"
00113 " and SAVE_LAYER");
00114
00115 RawData::RawData(const DAQ_PktHdr_t* h, const uint8_t* p)
00116 {
00117 pkth = h;
00118 data = p;
00119 len = h->caplen;
00120 }
00121
00122 //-------------------------------------------------------------------------
00123 // Encode/Decode functions
00124 //-------------------------------------------------------------------------
00125 void PacketManager::decode(
00126 Packet* p, const DAQ_PktHdr_t* pkthdr, const uint8_t* pkt, bool cooked)
00127 {
00128 Profile profile(decodePerfStats);
00129
00130 DecodeData unsure_encap_ptrs;
00131
00132 ProtocolIndex mapped_prot = CodecManager::grinder;
00133 ProtocolId prev_prot_id = CodecManager::grinder_id;
00134
00135 RawData raw(pkthdr, pkt);
00136 CodecData codec_data(ProtocolId::FINISHED_DECODE);
00137
00138 if ( cooked )
00139 codec_data.codec_flags |= CODEC_STREAM_REBUILT;
00140
00141 // initialize all Packet information
00142 p->reset();
00143 p->pkth = pkthdr;
00144 p->pkt = pkt;
00145 layer::set_packet_pointer(p);
00146
00147 //upload_packet(p, pkthdr->caplen);
00148
00149 s_stats[total_processed]++;
00150
00151 upload_packet(p);
00152
00153 // loop until the protocol id is no longer valid
00154 while (CodecManager::s_protocols[mapped_prot]->decode(raw, codec_data, p->ptrs))
00155 {
00156 DebugFormat(DEBUG_DECODE, "Codec %s (protocol_id: %hu:"
00157 "ip header starts at: %p, length is %d\n",
00158 CodecManager::s_protocols[mapped_prot]->get_name(),
00159 static_cast<uint16_t>(codec_data.next_prot_id), pkt, codec_data.lyr_len);
00160
00161 if ( codec_data.codec_flags & CODEC_ETHER_NEXT )
00162 {
00163 if ( codec_data.next_prot_id < ProtocolId::ETHERTYPE_MINIMUM )
00164 {
00165 DetectionEngine::queue_event(GID_DECODE, DECODE_BAD_ETHER_TYPE);
00166 break;
00167 }
00168 codec_data.codec_flags &= ~CODEC_ETHER_NEXT;
00169 }
00170
00171 /*
00172 * We only want the layer immediately following SAVE_LAYER to have the
00173 * UNSURE_ENCAP flag set. So, if this is a SAVE_LAYER, zero out the
00174 * bit and the next time around, when this is no longer SAVE_LAYER,
00175 * we will zero out the UNSURE_ENCAP flag.
00176 */
00177 if (codec_data.codec_flags & CODEC_SAVE_LAYER)
00178 {
00179 codec_data.codec_flags &= ~CODEC_SAVE_LAYER;
00180 unsure_encap_ptrs = p->ptrs;
00181 }
00182 else
00183 {
00184 codec_data.codec_flags &= ~CODEC_UNSURE_ENCAP;
00185 }
00186
00187 if (codec_data.proto_bits & (PROTO_BIT__IP | PROTO_BIT__IP6_EXT))
00188 {
00189 // FIXIT-M refactor when ip_proto's become an array
00190 if ( p->is_fragment() )
00191 {
00192 if ( prev_prot_id == ProtocolId::FRAGMENT )
00193 {
00194 const ip::IP6Frag* const fragh =
00195 reinterpret_cast<const ip::IP6Frag*>(raw.data);
00196 p->ip_proto_next = fragh->next();
00197 }
00198 else
00199 {
00200 p->ip_proto_next = p->ptrs.ip_api.get_ip4h()->proto();
00201 }
00202 }
00203 else
00204 {
00205 if(codec_data.next_prot_id != ProtocolId::FINISHED_DECODE)
00206 p->ip_proto_next = convert_protocolid_to_ipprotocol(codec_data.next_prot_id);
00207 }
00208 }
00209
00210 // If we have reached the MAX_LAYERS, we keep decoding
00211 // but no longer keep track of the layers.
00212 if ( p->num_layers == CodecManager::max_layers )
00213 DetectionEngine::queue_event(GID_DECODE, DECODE_TOO_MANY_LAYERS);
00214 else
00215 push_layer(p, prev_prot_id, raw.data, codec_data.lyr_len);
00216
00217 // internal statistics and record keeping
00218 s_stats[mapped_prot + stat_offset]++; // add correct decode for previous layer
00219 mapped_prot = CodecManager::s_proto_map[to_utype(codec_data.next_prot_id)];
00220 prev_prot_id = codec_data.next_prot_id;
00221
00222 // set for next call
00223 const uint16_t curr_lyr_len = codec_data.lyr_len + codec_data.invalid_bytes;
00224 assert(curr_lyr_len <= raw.len);
00225 raw.len -= curr_lyr_len;
00226 raw.data += curr_lyr_len;
00227 p->proto_bits |= codec_data.proto_bits;
00228 codec_data.next_prot_id = ProtocolId::FINISHED_DECODE;
00229 codec_data.lyr_len = 0;
00230 codec_data.invalid_bytes = 0;
00231 codec_data.proto_bits = 0;
00232 }
00233
00234 DebugFormat(DEBUG_DECODE, "Codec %s (protocol_id: %hu: ip header"
00235 " starts at: %p, length is %lu\n",
00236 CodecManager::s_protocols[mapped_prot]->get_name(),
00237 static_cast<uint16_t>(prev_prot_id), pkt, (unsigned long)codec_data.lyr_len);
00238
00239 if ( p->num_layers > 0 )
00240 s_stats[mapped_prot + stat_offset]++;
00241
00242 // if the final protocol ID is not the default codec, a Codec failed
00243 if (prev_prot_id != ProtocolId::FINISHED_DECODE or p->num_layers == 0 )
00244 {
00245 if (codec_data.codec_flags & CODEC_UNSURE_ENCAP)
00246 {
00247 p->ptrs = unsure_encap_ptrs;
00248
00249 switch (p->layers[p->num_layers-1].prot_id)
00250 {
00251 case ProtocolId::ESP:
00252 // Hardcoding ESP because we trust iff the layer
00253 // immediately preceding the fail is ESP.
00254 p->ptrs.decode_flags |= DECODE_PKT_TRUST;
00255 break;
00256
00257 case ProtocolId::TEREDO:
00258 // if we just decoded teredo and the next
00259 // layer fails, we made a mistake. Therefore,
00260 // remove this bit.
00261 pop_teredo(p, raw);
00262 break;
00263 default:
00264 ;
00265 } /* switch */
00266 }
00267 else
00268 {
00269 if ( (p->num_layers > 0) &&
00270 (p->layers[p->num_layers-1].prot_id == ProtocolId::TEREDO) &&
00271 (prev_prot_id == ProtocolId::IPV6) )
00272 {
00273 pop_teredo(p, raw);
00274 }
00275
00276 // if the codec exists, it failed
00277 if (CodecManager::s_proto_map[to_utype(prev_prot_id)])
00278 {
00279 s_stats[discards]++;
00280 }
00281 else
00282 {
00283 s_stats[other_codecs]++;
00284
00285 if ( (to_utype(ProtocolId::MIN_UNASSIGNED_IP_PROTO) <= to_utype(prev_prot_id)) &&
00286 (to_utype(prev_prot_id) <= std::numeric_limits<uint8_t>::max()) &&
00287 !(codec_data.codec_flags & CODEC_STREAM_REBUILT) )
00288 {
00289 DetectionEngine::queue_event(GID_DECODE, DECODE_IP_UNASSIGNED_PROTO);
00290 }
00291 }
00292 }
00293 }
00294
00295 // set any final Packet fields
00296 p->data = raw.data;
00297 p->dsize = (uint16_t)raw.len;
00298 p->proto_bits |= codec_data.proto_bits;
00299
00300 if ( !p->proto_bits )
00301 p->proto_bits = PROTO_BIT__OTHER;
00302 }
00303
00304 //-------------------------------------------------------------------------
00305 // encoders operate layer by layer:
00306 //-------------------------------------------------------------------------
00307
00308 //-------------------------------------------------------------------------
00309 // encoders:
00310 // - raw pkt data only, no need for Packet stuff except to facilitate
00311 // encoding
00312 // - don't include original options
00313 // - inner layer differs from original (eg tcp data segment becomes rst)
00314 // - must ensure proper ttl/hop limit for reverse direction
00315 //
00316 // iterate over decoded layers and encode the response packet. actually
00317 // make nested calls. on the way in we setup invariant stuff and as we
00318 // unwind the stack we finish up encoding in a more normal fashion (now
00319 // the outer layer knows the length of the inner layer, etc.).
00320 //
00321 // when multiple responses are sent, both forwards and backwards directions,
00322 // or multiple ICMP types (unreachable port, host, net), it may be possible
00323 // to reuse the 1st encoding and just tweak it. optimization for later
00324 // consideration.
00325
00326 // pci is copied from in to out
00327 // * addresses / ports are swapped if !fwd
00328 // * options, etc. are stripped
00329 // * checksums etc. are set
00330 // * if next layer is udp, it is set to icmp unreachable w/udp
00331 // * if next layer is tcp, it becomes a tcp rst or tcp fin w/opt data
00332 //-------------------------------------------------------------------------
00333
00334 static inline uint8_t GetTTL(const Packet* const p, bool forward)
00335 {
00336 char dir;
00337 uint8_t ttl;
00338 const bool outer = p->ptrs.ip_api.is_ip();
00339
00340 if ( !p->flow )
00341 return 0;
00342
00343 if ( p->is_from_client() )
00344 dir = forward ? FROM_CLIENT : FROM_SERVER;
00345 else
00346 dir = forward ? FROM_SERVER : FROM_CLIENT;
00347
00348 // outermost ip is considered to be outer here,
00349 // even if it is the only ip layer ...
00350 ttl = Stream::get_flow_ttl(p->flow, dir, outer);
00351
00352 // if we don't get outer, we use inner
00353 if ( 0 == ttl && outer )
00354 ttl = Stream::get_flow_ttl(p->flow, dir, false);
00355
00356 return ttl;
00357 }
00358
00359 bool PacketManager::encode(const Packet* p,
00360 EncodeFlags flags,
00361 uint8_t lyr_start,
00362 IpProtocol next_prot,
00363 Buffer& buf)
00364 {
00365 if ( Packet* pe = DetectionEngine::get_encode_packet() )
00366 p = pe;
00367
00368 uint8_t ttl = GetTTL(p, (flags & ENC_FLAG_FWD));
00369 if ( ttl )
00370 flags |= ENC_FLAG_TTL;
00371 else
00372 ttl = 0;
00373
00374 if ( SFDAQ::forwarding_packet(p->pkth) )
00375 flags |= ENC_FLAG_INLINE;
00376
00377 ip::IpApi tmp_api;
00378 EncState enc(tmp_api, flags, next_prot, ttl, p->dsize);
00379
00380 const Layer* const lyrs = p->layers;
00381 int8_t outer_layer = lyr_start;
00382 int8_t inner_layer = lyr_start;
00383
00384 // We need the IP layer associated with every protocol
00385 // so checksums can be computed.
00386 while (layer::set_inner_ip_api(p, tmp_api, inner_layer))
00387 {
00388 for (int i = outer_layer; i > inner_layer; --i)
00389 {
00390 const Layer& l = lyrs[i];
00391 ProtocolIndex mapped_prot =
00392 i ? CodecManager::s_proto_map[to_utype(l.prot_id)] : CodecManager::grinder;
00393 if (!CodecManager::s_protocols[mapped_prot]->encode(l.start, l.length, enc, buf, p->flow))
00394 {
00395 return false;
00396 }
00397 }
00398 outer_layer = inner_layer;
00399 // inner_layer is set in 'layer::set_inner_ip_api'
00400 }
00401
00402 // Now, we can encode all of the layers between the DLT and
00403 // outermost IP layer
00404 tmp_api.reset();
00405 for (int i = outer_layer; i >= 0; --i)
00406 {
00407 const Layer& l = lyrs[i];
00408 ProtocolIndex mapped_prot =
00409 i ? CodecManager::s_proto_map[to_utype(l.prot_id)] : CodecManager::grinder;
00410
00411 if (!CodecManager::s_protocols[mapped_prot]->encode(l.start, l.length, enc, buf, p->flow))
00412 {
00413 return false;
00414 }
00415 }
00416
00417 return true;
00418 }
00419
00420 const uint8_t* PacketManager::encode_response(
00421 TcpResponse type, EncodeFlags flags, const Packet* p, uint32_t& len,
00422 const uint8_t* const payload, uint32_t payload_len)
00423 {
00424 Buffer buf(s_pkt.data(), s_pkt.size());
00425
00426 switch (type)
00427 {
00428 case TcpResponse::FIN:
00429 if (payload && (payload_len > 0))
00430 {
00431 if (!buf.allocate(payload_len))
00432 return nullptr;
00433
00434 memcpy(buf.data(), payload, payload_len);
00435 flags |= ENC_FLAG_PAY;
00436 }
00437 flags |= ENC_FLAG_FIN;
00438 break;
00439
00440 case TcpResponse::PUSH:
00441 if (payload && (payload_len > 0))
00442 {
00443 if (!buf.allocate(payload_len))
00444 return nullptr;
00445
00446 memcpy(buf.data(), payload, payload_len);
00447 flags |= ENC_FLAG_PAY;
00448 }
00449 flags |= ENC_FLAG_PSH;
00450 break;
00451
00452 case TcpResponse::RST: // No payload, so do nothing.
00453 default: // future proof
00454 break;
00455 }
00456
00457 // FIXIT-M check flags if we should skip something
00458 if (encode(p, flags, p->num_layers-1, IpProtocol::PROTO_NOT_SET, buf))
00459 {
00460 len = buf.size();
00461 return buf.data() + buf.off;
00462 }
00463
00464 len = 0;
00465 return nullptr;
00466 }
00467
00468 const uint8_t* PacketManager::encode_reject(UnreachResponse type,
00469 EncodeFlags flags, const Packet* p, uint32_t& len)
00470 {
00471 Buffer buf(s_pkt.data(), s_pkt.size());
00472
00473 if (p->is_ip4())
00474 {
00475 // FIXIT-M check flags if we should skip something
00476 const int inner_ip_index = layer::get_inner_ip_lyr_index(p);
00477 assert(inner_ip_index >= 0);
00478 assert(inner_ip_index+1 < p->num_layers);
00479
00480 /* Building this packet from the inside out */
00481 if (!buf.allocate(icmp::ICMP_UNREACH_DATA_LEN))
00482 return nullptr;
00483
00484 memcpy(buf.data(), p->layers[inner_ip_index+1].start, icmp::ICMP_UNREACH_DATA_LEN);
00485
00486 const ip::IP4Hdr* const ip4h =
00487 reinterpret_cast<const ip::IP4Hdr*>(p->layers[inner_ip_index].start);
00488 const uint8_t ip_len = ip4h->hlen();
00489
00490 if (!buf.allocate(ip_len))
00491 return nullptr;
00492 memcpy(buf.data(), ip4h, ip_len);
00493
00494 // If this returns false, we're down pig creek.
00495 if (!buf.allocate(sizeof(icmp::Icmp4Base)))
00496 return nullptr;
00497
00498 icmp::Icmp4Base* const icmph = reinterpret_cast<icmp::Icmp4Base*>(buf.data());
00499 icmph->type = icmp::IcmpType::DEST_UNREACH;
00500 icmph->csum = 0;
00501 icmph->opt32 = 0;
00502
00503 switch (type)
00504 {
00505 case UnreachResponse::NET:
00506 icmph->code = icmp::IcmpCode::NET_UNREACH;
00507 break;
00508 case UnreachResponse::HOST:
00509 icmph->code = icmp::IcmpCode::HOST_UNREACH;
00510 break;
00511 case UnreachResponse::PORT:
00512 icmph->code = icmp::IcmpCode::PORT_UNREACH;
00513 break;
00514 case UnreachResponse::FWD:
00515 icmph->code = icmp::IcmpCode::PKT_FILTERED;
00516 break;
00517 default: // future proofing
00518 icmph->code = icmp::IcmpCode::PORT_UNREACH;
00519 }
00520
00521 icmph->csum = checksum::icmp_cksum((uint16_t*)buf.data(), buf.size());
00522
00523 if (encode(p, flags, inner_ip_index, IpProtocol::ICMPV4, buf))
00524 {
00525 len = buf.size();
00526 return buf.data() + buf.off;
00527 }
00528
00529 len = 0;
00530 return nullptr;
00531 }
00532 else if (p->is_ip6())
00533 {
00534 // FIXIT-M check flags if we should skip ip6_options
00535 const int inner_ip_index = layer::get_inner_ip_lyr_index(p);
00536 assert(inner_ip_index >= 0);
00537 assert(inner_ip_index+1 < p->num_layers);
00538
00539 // FIXIT-L copy up to minimum MTU worth of data
00540 // FIXIT-L check if we have the full 8 bytes of data.
00541 if (!buf.allocate(icmp::ICMP_UNREACH_DATA_LEN))
00542 return nullptr;
00543 memcpy(buf.data(), p->layers[inner_ip_index+1].start, icmp::ICMP_UNREACH_DATA_LEN);
00544
00545 // copy original ip header
00546 if (!buf.allocate(ip::IP6_HEADER_LEN))
00547 return nullptr;
00548 const ip::IP6Hdr* const ip6h = p->ptrs.ip_api.get_ip6h();
00549 memcpy(buf.data(), ip6h, ip::IP6_HEADER_LEN);
00550
00551 if (!buf.allocate(sizeof(icmp::Icmp6Hdr)))
00552 return nullptr;
00553
00554 icmp::Icmp6Hdr* const icmph = reinterpret_cast<icmp::Icmp6Hdr*>(buf.data());
00555 icmph->type = icmp::Icmp6Types::DESTINATION_UNREACHABLE;
00556 icmph->csum = 0;
00557 icmph->opt32 = 0;
00558
00559 switch (type)
00560 {
00561 case UnreachResponse::NET:
00562 icmph->code = icmp::Icmp6Code::UNREACH_NET;
00563 break;
00564 case UnreachResponse::HOST:
00565 icmph->code = icmp::Icmp6Code::UNREACH_HOST;
00566 break;
00567 case UnreachResponse::PORT:
00568 icmph->code = icmp::Icmp6Code::UNREACH_PORT;
00569 break;
00570 case UnreachResponse::FWD:
00571 icmph->code = icmp::Icmp6Code::UNREACH_FILTER_PROHIB;
00572 break;
00573 default: // future proofing
00574 icmph->code = icmp::Icmp6Code::UNREACH_PORT;
00575 }
00576
00577 checksum::Pseudoheader6 ps6;
00578 const int ip_len = buf.size();
00579 memcpy(ps6.sip, ip6h->get_src()->u6_addr8, sizeof(ps6.sip));
00580 memcpy(ps6.dip, ip6h->get_dst()->u6_addr8, sizeof(ps6.dip));
00581 ps6.zero = 0;
00582 ps6.protocol = IpProtocol::ICMPV6;
00583 ps6.len = htons((uint16_t)(ip_len));
00584
00585 icmph->csum = checksum::icmp_cksum((uint16_t*)buf.data(), ip_len, &ps6);
00586
00587 if (encode(p, flags, inner_ip_index, IpProtocol::ICMPV6, buf))
00588 {
00589 len = buf.size();
00590 return buf.data() + buf.off;
00591 }
00592
00593 len = 0;
00594 return nullptr;
00595 }
00596 else
00597 {
00598 return nullptr;
00599 }
00600 }
00601
00602 static void set_hdr(
00603 const Packet* p, Packet* c, const DAQ_PktHdr_t* phdr, uint32_t opaque)
00604 {
00605 c->reset();
00606
00607 if ( !phdr )
00608 phdr = p->pkth;
00609
00610 DAQ_PktHdr_t* pkth = const_cast<DAQ_PktHdr_t*>(c->pkth);
00611 pkth->ingress_index = phdr->ingress_index;
00612 pkth->ingress_group = phdr->ingress_group;
00613 pkth->egress_index = phdr->egress_index;
00614 pkth->egress_group = phdr->egress_group;
00615 pkth->flags = phdr->flags & (~DAQ_PKT_FLAG_HW_TCP_CS_GOOD);
00616 pkth->address_space_id = phdr->address_space_id;
00617 pkth->opaque = opaque;
00618 }
00619
00620 //-------------------------------------------------------------------------
00621 // formatters:
00622 // - these packets undergo detection
00623 // - need to set Packet stuff except for frag which calls grinder
00624 // - include original options except for frag inner ip
00625 // - inner layer header is very similar but payload differs
00626 // - original ttl is always used
00627 //-------------------------------------------------------------------------
00628
00629 int PacketManager::format_tcp(
00630 EncodeFlags, const Packet* p, Packet* c, PseudoPacketType type,
00631 const DAQ_PktHdr_t* phdr, uint32_t opaque)
00632 {
00633 c->reset();
00634 set_hdr(p, c, phdr, opaque);
00635
00636 c->packet_flags |= PKT_PSEUDO;
00637 c->pseudo_type = type;
00638
00639 // cooked packet gets same policy as raw
00640 c->user_inspection_policy_id = p->user_inspection_policy_id;
00641 c->user_ips_policy_id = p->user_ips_policy_id;
00642 c->user_network_policy_id = p->user_network_policy_id;
00643
00644 // setup pkt capture header
00645 DAQ_PktHdr_t* pkth = const_cast<DAQ_PktHdr_t*>(c->pkth);
00646 pkth->caplen = 0;
00647 pkth->pktlen = 0;
00648 pkth->ts = p->pkth->ts;
00649
00650 total_rebuilt_pkts++;
00651 return 0;
00652 }
00653
00654 int PacketManager::encode_format(
00655 EncodeFlags f, const Packet* p, Packet* c, PseudoPacketType type,
00656 const DAQ_PktHdr_t* phdr, uint32_t opaque)
00657 {
00658 int i;
00659 int len;
00660 bool update_ip4_len = false;
00661 uint8_t num_layers = p->num_layers;
00662
00663 if ( num_layers <= 0 )
00664 return -1;
00665
00666 c->reset();
00667 set_hdr(p, c, phdr, opaque);
00668
00669 if ( f & ENC_FLAG_NET )
00670 {
00671 num_layers = layer::get_inner_ip_lyr_index(p) + 1;
00672
00673 if (num_layers == 0) // FIXIT-L is this an extraneous check?
00674 return -1;
00675 }
00676 else if ( f & ENC_FLAG_DEF )
00677 {
00678 /*
00679 * By its definitinos, this flag means 'stop before innermost ip4
00680 * opts or ip6 frag header'. So, stop after the ip4 layer IP4 will format itself, and now
00681 * we ensure that the ip6_frag header is not copied too.
00682 */
00683
00684 if ( p->is_ip6() )
00685 {
00686 num_layers = layer::get_inner_ip6_frag_index(p);
00687 }
00688 else
00689 {
00690 num_layers = layer::get_inner_ip_lyr_index(p) + 1;
00691 update_ip4_len = true;
00692 }
00693
00694 if (num_layers <= 0)
00695 return -1;
00696 }
00697
00698 // copy raw packet data to clone
00699 Layer* lyr = (Layer*)p->layers + num_layers - 1;
00700 len = lyr->start - p->pkt + lyr->length;
00701 memcpy((void*)c->pkt, p->pkt, len);
00702
00703 if ( update_ip4_len )
00704 {
00705 ip::IP4Hdr* ip4h = reinterpret_cast<ip::IP4Hdr*>(const_cast<uint8_t*>(lyr->start));
00706 lyr->length = ip::IP4_HEADER_LEN;
00707 ip4h->set_ip_len(ip::IP4_HEADER_LEN);
00708 ip4h->set_hlen(ip::IP4_HEADER_LEN >> 2);
00709 }
00710
00711 const bool reverse = !(f & ENC_FLAG_FWD);
00712
00713 // set up and format layers
00714 for ( i = 0; i < num_layers; i++ )
00715 {
00716 const uint8_t* b = c->pkt + (p->layers[i].start - p->pkt); // == c->pkt + p->layers[i].len
00717 lyr = c->layers + i;
00718
00719 lyr->prot_id = p->layers[i].prot_id;
00720 lyr->length = p->layers[i].length;
00721 lyr->start = b;
00722
00723 // NOTE: this must always go from outer to inner
00724 // to ensure a valid ip header
00725 ProtocolIndex mapped_prot =
00726 i ? CodecManager::s_proto_map[to_utype(lyr->prot_id)] : CodecManager::grinder;
00727
00728 CodecManager::s_protocols[mapped_prot]->format(
00729 reverse, const_cast<uint8_t*>(lyr->start), c->ptrs);
00730 }
00731
00732 // setup payload info
00733 c->num_layers = num_layers;
00734 c->data = lyr->start + lyr->length;
00735 len = c->data - c->pkt;
00736
00737 // len < ETHERNET_HEADER_LEN + VLAN_HEADER + ETHERNET_MTU
00738 assert((unsigned)len < Codec::PKT_MAX - c->max_dsize);
00739
00740 c->proto_bits = p->proto_bits;
00741 c->ip_proto_next = p->ip_proto_next;
00742 c->packet_flags |= PKT_PSEUDO;
00743 c->pseudo_type = type;
00744
00745 // cooked packet gets same policy as raw
00746 c->user_inspection_policy_id = p->user_inspection_policy_id;
00747 c->user_ips_policy_id = p->user_ips_policy_id;
00748 c->user_network_policy_id = p->user_network_policy_id;
00749
00750 // setup pkt capture header
00751 DAQ_PktHdr_t* pkth = const_cast<DAQ_PktHdr_t*>(c->pkth);
00752 pkth->caplen = len;
00753 pkth->pktlen = len;
00754 pkth->ts = p->pkth->ts;
00755
00756 layer::set_packet_pointer(c); // ensure we are looking at the new packet
00757 total_rebuilt_pkts++;
00758 return 0;
00759 }
00760
00761 //-------------------------------------------------------------------------
00762 // updaters: these functions set length and checksum fields, only needed
00763 // when a packet is modified. some packets only have replacements so only
00764 // the checksums need to be updated. we always set the length rather than
00765 // checking each time if needed.
00766 //-------------------------------------------------------------------------
00767
00768 static inline void add_flag(UpdateFlags& flags,
00769 UpdateFlags flag_to_add,
00770 const Packet* const p,
00771 decltype(Packet::packet_flags)pkt_flag) // future proofing.
00772 {
00773 if ( p->packet_flags & pkt_flag )
00774 flags |= flag_to_add;
00775 }
00776
00777 void PacketManager::encode_update(Packet* p)
00778 {
00779 uint32_t len = p->dsize;
00780
00781 UpdateFlags flags = 0;
00782 add_flag(flags, UPD_COOKED, p, PKT_PSEUDO);
00783 add_flag(flags, UPD_MODIFIED, p, PKT_MODIFIED);
00784 add_flag(flags, UPD_RESIZED, p, PKT_RESIZED);
00785 add_flag(flags, UPD_REBUILT_FRAG, p, PKT_REBUILT_FRAG);
00786
00787 int8_t outer_layer = p->num_layers-1;
00788 int8_t inner_layer = p->num_layers-1;
00789 const Layer* const lyr = p->layers;
00790 ip::IpApi tmp_api;
00791
00792 // update the rest of the ip layers with the correct IP reference.
00793 while (layer::set_inner_ip_api(p, tmp_api, inner_layer))
00794 {
00795 for (int i = outer_layer; i > inner_layer; --i)
00796 {
00797 const Layer& l = lyr[i];
00798 ProtocolIndex mapped_prot = i ?
00799 CodecManager::s_proto_map[to_utype(l.prot_id)] : CodecManager::grinder;
00800
00801 CodecManager::s_protocols[mapped_prot]->update(
00802 tmp_api, flags, const_cast<uint8_t*>(l.start), l.length, len);
00803 }
00804 outer_layer = inner_layer;
00805 // inner_layer is set in 'layer::set_inner_ip_api'
00806 }
00807
00808 tmp_api.reset();
00809 for (int i = outer_layer; i >= 0; --i)
00810 {
00811 const Layer& l = lyr[i];
00812 ProtocolIndex mapped_prot = CodecManager::s_proto_map[to_utype(l.prot_id)];
00813 CodecManager::s_protocols[mapped_prot]->update(
00814 tmp_api, flags, const_cast<uint8_t*>(l.start), l.length, len);
00815 }
00816
00817 // see IP6_Update() for an explanation of this ...
00818 // FIXIT-L is this second statement really necessary?
00819 // PKT_RESIZED include PKT_MODIFIED ... so get rid of that extra flag
00820 if ( !(p->packet_flags & PKT_MODIFIED)
00821 || (p->packet_flags & (PKT_RESIZED & ~PKT_MODIFIED))
00822 )
00823 {
00824 DAQ_PktHdr_t* pkth = const_cast<DAQ_PktHdr_t*>(p->pkth);
00825 pkth->caplen = len;
00826 pkth->pktlen = len;
00827 }
00828 }
00829
00830 //-------------------------------------------------------------------------
00831 // codec support and statistics
00832 //-------------------------------------------------------------------------
00833
00834 PegCount PacketManager::get_rebuilt_packet_count()
00835 { return total_rebuilt_pkts; }
00836
00837 uint16_t PacketManager::encode_get_max_payload(const Packet* p)
00838 {
00839 if ( !p->num_layers )
00840 return 0;
00841
00842 const Layer& l = p->layers[p->num_layers - 1];
00843 return ETHERNET_MTU - (l.start - p->layers[0].start) - l.length;
00844 }
00845
00846 void PacketManager::dump_stats()
00847 {
00848 std::vector<const char*> pkt_names;
00849
00850 // zero out the default codecs
00851 g_stats[3] = 0;
00852 g_stats[CodecManager::s_proto_map[to_utype(ProtocolId::FINISHED_DECODE)] + stat_offset] = 0;
00853
00854 for (unsigned int i = 0; i < stat_names.size(); i++)
00855 pkt_names.push_back(stat_names[i]);
00856
00857 for (int i = 0; CodecManager::s_protocols[i] != nullptr; i++)
00858 pkt_names.push_back(CodecManager::s_protocols[i]->get_name());
00859
00860 show_percent_stats((PegCount*)&g_stats, &pkt_names[0],
00861 (unsigned int)pkt_names.size(), "codec");
00862 }
00863
00864 void PacketManager::accumulate()
00865 {
00866 static std::mutex stats_mutex;
00867
00868 std::lock_guard<std::mutex> lock(stats_mutex);
00869 sum_stats(&g_stats[0], &s_stats[0], s_stats.size());
00870
00871 // mutex is automatically unlocked
00872 }
00873
00874 const char* PacketManager::get_proto_name(ProtocolId protocol)
00875 { return CodecManager::s_protocols[CodecManager::s_proto_map[to_utype(protocol)]]->get_name(); }
00876
00877 const char* PacketManager::get_proto_name(IpProtocol protocol)
00878 { return CodecManager::s_protocols[CodecManager::s_proto_map[to_utype(protocol)]]->get_name(); }
00879
00880 void PacketManager::log_protocols(TextLog* const text_log,
00881 const Packet* const p)
00882 {
00883 uint8_t num_layers = p->num_layers;
00884 const Layer* const lyr = p->layers;
00885
00886 if (num_layers != 0)
00887 {
00888 // Grinder is not in the layer array
00889 Codec* cd = CodecManager::s_protocols[CodecManager::grinder];
00890
00891 TextLog_Print(text_log, "%-.6s(DLT): ", cd->get_name());
00892 cd->log(text_log, lyr[0].start, lyr[0].length);
00893
00894 for (int i = 1; i < num_layers; i++)
00895 {
00896 const auto protocol = to_utype(lyr[i].prot_id);
00897 const uint8_t codec_offset = CodecManager::s_proto_map[protocol];
00898 cd = CodecManager::s_protocols[codec_offset];
00899
00900 TextLog_NewLine(text_log);
00901 TextLog_Print(text_log, "%-.*s", 6, cd->get_name());
00902
00903 if (protocol <= 0xFF)
00904 TextLog_Print(text_log, "(0x%02x)", protocol);
00905 else
00906 TextLog_Print(text_log, "(0x%04x)", protocol);
00907
00908 TextLog_Puts(text_log, ": ");
00909 cd->log(text_log, lyr[i].start, lyr[i].length);
00910 }
00911 }
00912 }
00913
END OF CODE