From: Josh Date: Wed, 6 Aug 2014 17:57:48 +0000 (-0400) Subject: UNTESTED - Removing All ICMP embedded IP/TCP/UDP/ICMP data from Paket X-Git-Tag: 3.0.0-233~1426^2~8^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=62dede9485aa247659c849bf4e63219dcb493567;p=thirdparty%2Fsnort3.git UNTESTED - Removing All ICMP embedded IP/TCP/UDP/ICMP data from Paket --- diff --git a/src/codecs/codec_api.cc b/src/codecs/codec_api.cc index 8199cece6..f0066f0f7 100644 --- a/src/codecs/codec_api.cc +++ b/src/codecs/codec_api.cc @@ -56,6 +56,8 @@ extern const BaseApi* cd_frag; extern const BaseApi* cd_gre; extern const BaseApi* cd_gtp; extern const BaseApi* cd_hopopts; +extern const BaseApi* cd_ip4_embedded_in_icmp; +extern const BaseApi* cd_ip6_embedded_in_icmp; extern const BaseApi* cd_igmp; extern const BaseApi* cd_mobility; extern const BaseApi* cd_mpls; @@ -74,6 +76,7 @@ extern const BaseApi* cd_vlan; #ifndef NO_NON_ETHER_DECODER extern const BaseApi* cd_eapol; extern const BaseApi* cd_linux_sll; +extern const BaseApi* cd_ppp; extern const BaseApi* cd_wlan; #endif @@ -109,6 +112,8 @@ const BaseApi* codecs[] = cd_gre, cd_gtp, cd_hopopts, + cd_ip4_embedded_in_icmp, + cd_ip6_embedded_in_icmp, cd_igmp, cd_mobility, cd_mpls, @@ -127,6 +132,7 @@ const BaseApi* codecs[] = #ifndef NO_NON_ETHER_DECODER cd_eapol, cd_linux_sll, + cd_ppp, cd_wlan, #endif diff --git a/src/codecs/ip/cd_esp.cc b/src/codecs/ip/cd_esp.cc index 1d39f360d..11e8d04bc 100644 --- a/src/codecs/ip/cd_esp.cc +++ b/src/codecs/ip/cd_esp.cc @@ -138,8 +138,8 @@ bool EspCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len, different valid next_header. The DECODE__UNSURE_ENCAP flag tells the next decoder stage to silently ignore invalid headers. */ p->decode_flags |= DECODE__UNSURE_ENCAP; + p->decode_flags |= DECODE__TRUST_ON_FAIL; const_cast(raw_len) -= (ESP_AUTH_DATA_LEN + ESP_TRAILER_LEN); - p->decode_flags |= DECODE__ESP; } else { diff --git a/src/codecs/ip/cd_icmp4.cc b/src/codecs/ip/cd_icmp4.cc index ef69689c3..b8b24a9ba 100644 --- a/src/codecs/ip/cd_icmp4.cc +++ b/src/codecs/ip/cd_icmp4.cc @@ -25,12 +25,6 @@ #include "config.h" #endif -#ifdef HAVE_DUMBNET_H -#include -#else -#include -#endif - #include "framework/codec.h" #include "snort.h" #include "protocols/icmp4.h" @@ -57,9 +51,8 @@ public: virtual bool encode(EncState*, Buffer* out, const uint8_t* raw_in); virtual bool update(Packet*, Layer*, uint32_t* len); virtual void format(EncodeFlags, const Packet* p, Packet* c, Layer*); -private: - void DecodeICMPEmbeddedIP(const uint8_t *pkt, const uint32_t len, Packet *p); +private: void ICMP4AddrTests (Packet* ); void ICMP4MiscTests (Packet *); @@ -91,9 +84,9 @@ void Icmp4Codec::get_protocol_ids(std::vector &v) * Returns: void function */ bool Icmp4Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, - Packet *p, uint16_t &lyr_len, uint16_t& /*next_prot_id*/) + Packet *p, uint16_t &lyr_len, uint16_t& next_prot_id) { - if(raw_len < icmp4::hdr_len()) + if(raw_len < icmp::hdr_len()) { DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "WARNING: Truncated ICMP4 header (%d bytes).\n", raw_len);); @@ -110,17 +103,17 @@ bool Icmp4Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, switch (p->icmph->type) { // fall through ... - case icmp4::IcmpType::SOURCE_QUENCH: - case icmp4::IcmpType::DEST_UNREACH: - case icmp4::IcmpType::REDIRECT: - case icmp4::IcmpType::TIME_EXCEEDED: - case icmp4::IcmpType::PARAMETERPROB: - case icmp4::IcmpType::ECHOREPLY: - case icmp4::IcmpType::ECHO: - case icmp4::IcmpType::ROUTER_ADVERTISE: - case icmp4::IcmpType::ROUTER_SOLICIT: - case icmp4::IcmpType::INFO_REQUEST: - case icmp4::IcmpType::INFO_REPLY: + case icmp::IcmpType::SOURCE_QUENCH: + case icmp::IcmpType::DEST_UNREACH: + case icmp::IcmpType::REDIRECT: + case icmp::IcmpType::TIME_EXCEEDED: + case icmp::IcmpType::PARAMETERPROB: + case icmp::IcmpType::ECHOREPLY: + case icmp::IcmpType::ECHO: + case icmp::IcmpType::ROUTER_ADVERTISE: + case icmp::IcmpType::ROUTER_SOLICIT: + case icmp::IcmpType::INFO_REQUEST: + case icmp::IcmpType::INFO_REPLY: if (raw_len < 8) { DEBUG_WRAP(DebugMessage(DEBUG_DECODE, @@ -133,8 +126,8 @@ bool Icmp4Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, } break; - case icmp4::IcmpType::TIMESTAMP: - case icmp4::IcmpType::TIMESTAMPREPLY: + case icmp::IcmpType::TIMESTAMP: + case icmp::IcmpType::TIMESTAMPREPLY: if (raw_len < 20) { DEBUG_WRAP(DebugMessage(DEBUG_DECODE, @@ -147,8 +140,8 @@ bool Icmp4Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, } break; - case icmp4::IcmpType::ADDRESS: - case icmp4::IcmpType::ADDRESSREPLY: + case icmp::IcmpType::ADDRESS: + case icmp::IcmpType::ADDRESSREPLY: if (raw_len < 12) { DEBUG_WRAP(DebugMessage(DEBUG_DECODE, @@ -182,26 +175,26 @@ bool Icmp4Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, } } - lyr_len = icmp4::hdr_len(); + lyr_len = icmp::hdr_len(); DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "ICMP type: %d code: %d\n", p->icmph->type, p->icmph->code);); switch(p->icmph->type) { - case icmp4::IcmpType::ECHO: + case icmp::IcmpType::ECHO: ICMP4AddrTests(p); // fall through ... - case icmp4::IcmpType::ECHOREPLY: + case icmp::IcmpType::ECHOREPLY: /* setup the pkt id and seq numbers */ /* add the size of the echo ext to the data * ptr and subtract it from the data size */ lyr_len += sizeof(ICMPHdr::icmp_hun.idseq); break; - case icmp4::IcmpType::DEST_UNREACH: - if ((p->icmph->code == icmp4::IcmpCode::FRAG_NEEDED) + case icmp::IcmpType::DEST_UNREACH: + if ((p->icmph->code == icmp::IcmpCode::FRAG_NEEDED) && (ntohs(p->icmph->s_icmp_nextmtu) < 576)) { codec_events::decoder_event(p, DECODE_ICMP_PATH_MTU_DOS); @@ -209,13 +202,13 @@ bool Icmp4Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, /* Fall through */ - case icmp4::IcmpType::SOURCE_QUENCH: - case icmp4::IcmpType::REDIRECT: - case icmp4::IcmpType::TIME_EXCEEDED: - case icmp4::IcmpType::PARAMETERPROB: + case icmp::IcmpType::SOURCE_QUENCH: + case icmp::IcmpType::REDIRECT: + case icmp::IcmpType::TIME_EXCEEDED: + case icmp::IcmpType::PARAMETERPROB: /* account for extra 4 bytes in header */ lyr_len += 4; - DecodeICMPEmbeddedIP(raw_pkt + lyr_len, raw_len - lyr_len, p); + next_prot_id = IP_EMBEDDED_IN_ICMP4; break; default: @@ -232,7 +225,8 @@ bool Icmp4Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, return true; } - +// TODO: delete +#if 0 /* * Function: DecodeICMPEmbeddedIP(uint8_t *, const uint32_t, Packet *) * @@ -252,7 +246,7 @@ void Icmp4Codec::DecodeICMPEmbeddedIP(const uint8_t *pkt, const uint32_t len, Pa uint16_t orig_frag_offset; /* do a little validation */ - if(len < ipv4::hdr_len()) + if(len < ip::hdr_len()) { DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "ICMP: IP short header (%d bytes)\n", len);); @@ -367,7 +361,7 @@ void Icmp4Codec::DecodeICMPEmbeddedIP(const uint8_t *pkt, const uint32_t len, Pa return; } - +#endif void Icmp4Codec::ICMP4AddrTests (Packet* p) { @@ -376,7 +370,7 @@ void Icmp4Codec::ICMP4AddrTests (Packet* p) uint32_t dst = GET_DST_IP(p)->ip32[0]; // check all 32 bits; all set so byte order is irrelevant ... - if ( ipv4::is_broadcast(dst) ) + if ( ip::is_broadcast(dst) ) codec_events::decoder_event(p, DECODE_ICMP4_DST_BROADCAST); /* - don't use htonl for speed reasons - @@ -390,7 +384,7 @@ void Icmp4Codec::ICMP4AddrTests (Packet* p) // check the 'msn' (most significant nibble) ... msb_dst >>= 4; - if( ipv4::is_multicast(msb_dst) ) + if( ip::is_multicast(msb_dst) ) codec_events::decoder_event(p, DECODE_ICMP4_DST_MULTICAST); } @@ -398,51 +392,51 @@ void Icmp4Codec::ICMP4AddrTests (Packet* p) void Icmp4Codec::ICMP4MiscTests (Packet *p) { if ((p->dsize == 0) && - (p->icmph->type == icmp4::IcmpType::ECHO)) + (p->icmph->type == icmp::IcmpType::ECHO)) codec_events::decoder_event(p, DECODE_ICMP_PING_NMAP); if ((p->dsize == 0) && (p->icmph->s_icmp_seq == 666)) codec_events::decoder_event(p, DECODE_ICMP_ICMPENUM); - if ((p->icmph->type == icmp4::IcmpType::REDIRECT) && - (p->icmph->code == icmp4::IcmpCode::REDIR_HOST)) + if ((p->icmph->type == icmp::IcmpType::REDIRECT) && + (p->icmph->code == icmp::IcmpCode::REDIR_HOST)) codec_events::decoder_event(p, DECODE_ICMP_REDIRECT_HOST); - if ((p->icmph->type == icmp4::IcmpType::REDIRECT) && - (p->icmph->code == icmp4::IcmpCode::REDIR_NET)) + if ((p->icmph->type == icmp::IcmpType::REDIRECT) && + (p->icmph->code == icmp::IcmpCode::REDIR_NET)) codec_events::decoder_event(p, DECODE_ICMP_REDIRECT_NET); - if (p->icmph->type == icmp4::IcmpType::ECHOREPLY) + if (p->icmph->type == icmp::IcmpType::ECHOREPLY) { int i; for (i = 0; i < p->ip_option_count; i++) { - if ( ipv4::is_opt_rr(p->ip_options[i].code) ) + if (p->ip_options[i].is_opt_rr()) codec_events::decoder_event(p, DECODE_ICMP_TRACEROUTE_IPOPTS); } } - if ((p->icmph->type == icmp4::IcmpType::SOURCE_QUENCH) && - (p->icmph->code == icmp4::IcmpCode::SOURCE_QUENCH_CODE)) + if ((p->icmph->type == icmp::IcmpType::SOURCE_QUENCH) && + (p->icmph->code == icmp::IcmpCode::SOURCE_QUENCH_CODE)) codec_events::decoder_event(p, DECODE_ICMP_SOURCE_QUENCH); if ((p->dsize == 4) && - (p->icmph->type == icmp4::IcmpType::ECHO) && + (p->icmph->type == icmp::IcmpType::ECHO) && (p->icmph->s_icmp_seq == 0) && - (p->icmph->code == icmp4::IcmpCode::ECHO_CODE)) + (p->icmph->code == icmp::IcmpCode::ECHO_CODE)) codec_events::decoder_event(p, DECODE_ICMP_BROADSCAN_SMURF_SCANNER); - if ((p->icmph->type == icmp4::IcmpType::DEST_UNREACH) && - (p->icmph->code == icmp4::IcmpCode::PKT_FILTERED)) + if ((p->icmph->type == icmp::IcmpType::DEST_UNREACH) && + (p->icmph->code == icmp::IcmpCode::PKT_FILTERED)) codec_events::decoder_event(p, DECODE_ICMP_DST_UNREACH_ADMIN_PROHIBITED); - if ((p->icmph->type == icmp4::IcmpType::DEST_UNREACH) && - (p->icmph->code == icmp4::IcmpCode::PKT_FILTERED_HOST)) + if ((p->icmph->type == icmp::IcmpType::DEST_UNREACH) && + (p->icmph->code == icmp::IcmpCode::PKT_FILTERED_HOST)) codec_events::decoder_event(p, DECODE_ICMP_DST_UNREACH_DST_HOST_PROHIBITED); - if ((p->icmph->type == icmp4::IcmpType::DEST_UNREACH) && - (p->icmph->code == icmp4::IcmpCode::PKT_FILTERED_NET)) + if ((p->icmph->type == icmp::IcmpType::DEST_UNREACH) && + (p->icmph->code == icmp::IcmpCode::PKT_FILTERED_NET)) codec_events::decoder_event(p, DECODE_ICMP_DST_UNREACH_DST_NET_PROHIBITED); } @@ -469,14 +463,14 @@ bool Icmp4Codec::encode(EncState* enc, Buffer* out, const uint8_t* raw_in) uint8_t* p; IcmpHdr* ho; - if (!update_buffer(out, sizeof(*ho) + enc->ip_len + icmp4::unreach_data())) + if (!update_buffer(out, sizeof(*ho) + enc->ip_len + icmp::unreach_data())) return false; const uint16_t *hi = reinterpret_cast(raw_in); ho = reinterpret_cast(out->base); enc->proto = IPPROTO_ID_ICMPV4; - ho->type = icmp4::IcmpType::DEST_UNREACH; + ho->type = icmp::IcmpType::DEST_UNREACH; ho->code = get_icmp_code(enc->type); ho->cksum = 0; ho->unused = 0; @@ -487,7 +481,7 @@ bool Icmp4Codec::encode(EncState* enc, Buffer* out, const uint8_t* raw_in) // copy first 8 octets of original ip data (ie udp header) p += enc->ip_len; - memcpy(p, hi, icmp4::unreach_data()); + memcpy(p, hi, icmp::unreach_data()); ho->cksum = checksum::icmp_cksum((uint16_t *)ho, buff_diff(out, (uint8_t *)ho)); diff --git a/src/codecs/ip/cd_icmp6.cc b/src/codecs/ip/cd_icmp6.cc index 54a7369fc..7604af37f 100644 --- a/src/codecs/ip/cd_icmp6.cc +++ b/src/codecs/ip/cd_icmp6.cc @@ -53,8 +53,6 @@ public: Packet *, uint16_t &lyr_len, uint16_t &next_prot_id); virtual bool encode(EncState*, Buffer* out, const uint8_t* raw_in); virtual bool update(Packet*, Layer*, uint32_t* len); - virtual void format(EncodeFlags, const Packet* p, Packet* c, Layer*); - }; @@ -62,9 +60,6 @@ public: } // anonymous namespace -static void DecodeICMPEmbeddedIP6(const uint8_t *pkt, const uint32_t len, Packet *p); - - void Icmp6Codec::get_protocol_ids(std::vector& v) { v.push_back(IPPROTO_ICMPV6); @@ -75,7 +70,7 @@ void Icmp6Codec::get_protocol_ids(std::vector& v) //-------------------------------------------------------------------- bool Icmp6Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, - Packet* p, uint16_t &lyr_len, uint16_t & /* next_prot_id */) + Packet* p, uint16_t &lyr_len, uint16_t & next_prot_id ) { if(raw_len < icmp6::hdr_min_len()) { @@ -86,7 +81,7 @@ bool Icmp6Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, return false; } - p->icmp6h = reinterpret_cast(const_cast(raw_pkt)); + const icmp6::ICMP6Hdr* icmp6h = reinterpret_cast(raw_pkt); p->icmph = reinterpret_cast(raw_pkt); /* This is needed for icmp rules */ @@ -97,7 +92,7 @@ bool Icmp6Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, if(IS_IP4(p)) { - csum = checksum::cksum_add((uint16_t *)(p->icmp6h), raw_len); + csum = checksum::cksum_add((uint16_t *)(icmp6h), raw_len); } /* IPv6 traffic */ else @@ -109,7 +104,7 @@ bool Icmp6Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, ph6.protocol = GET_IPH_PROTO(p); ph6.len = htons((u_short)raw_len); - csum = checksum::icmp_cksum((uint16_t *)(p->icmp6h), raw_len, &ph6); + csum = checksum::icmp_cksum((uint16_t *)(icmp6h), raw_len, &ph6); } if(csum) { @@ -127,9 +122,9 @@ bool Icmp6Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, p->data = raw_pkt + icmp6::hdr_min_len(); DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "ICMP type: %d code: %d\n", - p->icmp6h->type, p->icmp6h->code);); + icmp6h->type, icmp6h->code);); - switch(p->icmp6h->type) + switch(icmp6h->type) { case icmp6::Icmp6Types::ECHO: case icmp6::Icmp6Types::REPLY: @@ -152,7 +147,6 @@ bool Icmp6Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, codec_events::decoder_event(p, DECODE_ICMP_DGRAM_LT_ICMPHDR); p->icmph = NULL; - p->icmp6h = NULL; return false; } break; @@ -170,7 +164,7 @@ bool Icmp6Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, codec_events::decoder_event(p, DECODE_ICMPV6_TOO_BIG_BAD_MTU); } lyr_len = icmp6::hdr_normal_len(); - DecodeICMPEmbeddedIP6(p->data, p->dsize, p); + next_prot_id = IP_EMBEDDED_IN_ICMP6; } else { @@ -180,7 +174,6 @@ bool Icmp6Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, codec_events::decoder_event(p, DECODE_ICMP_DGRAM_LT_ICMPHDR); p->icmph = NULL; - p->icmp6h = NULL; return false; } break; @@ -194,19 +187,19 @@ bool Icmp6Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, p->data += 4; p->dsize -= 4; - if (p->icmp6h->type == icmp6::Icmp6Types::UNREACH) + if (icmp6h->type == icmp6::Icmp6Types::UNREACH) { - if (p->icmp6h->code == 2) + if (icmp6h->code == 2) { codec_events::decoder_event(p, DECODE_ICMPV6_UNREACHABLE_NON_RFC_2463_CODE); } - else if (p->icmp6h->code > 6) + else if (icmp6h->code > 6) { codec_events::decoder_event(p, DECODE_ICMPV6_UNREACHABLE_NON_RFC_4443_CODE); } } lyr_len = icmp6::hdr_normal_len(); - DecodeICMPEmbeddedIP6(p->data, p->dsize, p); + next_prot_id = IP_EMBEDDED_IN_ICMP6; } else { @@ -216,7 +209,6 @@ bool Icmp6Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, codec_events::decoder_event(p, DECODE_ICMP_DGRAM_LT_ICMPHDR); p->icmph = NULL; - p->icmp6h = NULL; return false; } break; @@ -225,7 +217,7 @@ bool Icmp6Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, if (p->dsize >= (sizeof(ICMP6RouterAdvertisement) - icmp6::hdr_min_len())) { ICMP6RouterAdvertisement *ra = (ICMP6RouterAdvertisement *)raw_pkt; - if (p->icmp6h->code != 0) + if (icmp6h->code != 0) { codec_events::decoder_event(p, DECODE_ICMPV6_ADVERT_BAD_CODE); } @@ -243,7 +235,6 @@ bool Icmp6Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, codec_events::decoder_event(p, DECODE_ICMP_DGRAM_LT_ICMPHDR); p->icmph = NULL; - p->icmp6h = NULL; return false; } break; @@ -270,7 +261,6 @@ bool Icmp6Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, codec_events::decoder_event(p, DECODE_ICMP_DGRAM_LT_ICMPHDR); p->icmph = NULL; - p->icmp6h = NULL; return false; } break; @@ -297,14 +287,13 @@ bool Icmp6Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, codec_events::decoder_event(p, DECODE_ICMP_DGRAM_LT_ICMPHDR); p->icmph = NULL; - p->icmp6h = NULL; return false; } break; default: DEBUG_WRAP(DebugMessage(DEBUG_DECODE, - "WARNING: ICMP6_TYPE (type %d).\n", p->icmp6h->type);); + "WARNING: ICMP6_TYPE (type %d).\n", icmp6h->type);); codec_events::decoder_event(p, DECODE_ICMP6_TYPE_OTHER); lyr_len = icmp6::hdr_min_len(); @@ -317,6 +306,9 @@ bool Icmp6Codec::decode(const uint8_t* raw_pkt, const uint32_t& raw_len, } +// TODO: delete (along with any mention of this function) + +#if 0 /* * Function: DecodeICMPEmbeddedIP6(uint8_t *, const uint32_t, Packet *) @@ -414,6 +406,8 @@ static void DecodeICMPEmbeddedIP6(const uint8_t *pkt, const uint32_t len, Packet return; } +#endif + /****************************************************************** ******************** E N C O D E R ****************************** @@ -444,9 +438,9 @@ bool Icmp6Codec::encode (EncState* enc, Buffer* out, const uint8_t *raw_in) // copy first 8 octets of original ip data (ie udp header) // TBD: copy up to minimum MTU worth of data - if (!update_buffer(out, icmp4::unreach_data())) + if (!update_buffer(out, icmp::unreach_data())) return false; - memcpy(out->base, raw_in, icmp4::unreach_data()); + memcpy(out->base, raw_in, icmp::unreach_data()); // copy original ip header @@ -502,12 +496,6 @@ bool Icmp6Codec::update (Packet* p, Layer* lyr, uint32_t* len) return true; } -void Icmp6Codec::format (EncodeFlags, const Packet*, Packet* c, Layer* lyr) -{ - // TBD handle nested icmp6 layers - c->icmp6h = (ICMP6Hdr*)lyr->start; -} - //------------------------------------------------------------------------- // api //------------------------------------------------------------------------- diff --git a/src/codecs/ip/cd_igmp.cc b/src/codecs/ip/cd_igmp.cc index 1d2b2ccbd..9a3670651 100644 --- a/src/codecs/ip/cd_igmp.cc +++ b/src/codecs/ip/cd_igmp.cc @@ -74,7 +74,7 @@ bool IgmpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len, for(i=0; i< (int) p->ip_option_count; i++) { /* All IGMPv2 packets contain IP option code 148 (router alert). This vulnerability only applies to IGMPv3, so return early. */ - if (ipv4::is_opt_rtralt(p->ip_options[i].code)) { + if (p->ip_options[i].is_opt_rtralt()) { return true; /* No alert. */ } diff --git a/src/codecs/ip/cd_ipv4.cc b/src/codecs/ip/cd_ipv4.cc index c22d34212..d992ad4d8 100644 --- a/src/codecs/ip/cd_ipv4.cc +++ b/src/codecs/ip/cd_ipv4.cc @@ -167,7 +167,7 @@ bool Ipv4Codec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len, uint16_t hlen; /* ip header length */ /* do a little validation */ - if(raw_len < ipv4::hdr_len()) + if(raw_len < ip::IP4_HEADER_LEN) { DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "WARNING: Truncated IP4 header (%d bytes).\n", raw_len);); @@ -195,13 +195,14 @@ bool Ipv4Codec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len, } /* lay the IP struct over the raw data */ - p->inner_iph = p->iph = reinterpret_cast(const_cast(raw_pkt)); + IPHdr* iph = reinterpret_cast(const_cast(raw_pkt)); + p->inner_iph = p->iph = iph; /* * with datalink DLT_RAW it's impossible to differ ARP datagrams from IP. * So we are just ignoring non IP datagrams */ - if(ipv4::get_version((IPHdr*)raw_pkt) != 4) + if (iph->get_ver() != 4) { if ((p->decode_flags & DECODE__UNSURE_ENCAP) == 0) codec_events::decoder_event(p, DECODE_NOT_IPV4_DGRAM); @@ -215,10 +216,10 @@ bool Ipv4Codec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len, /* get the IP datagram length */ ip_len = ntohs(p->iph->ip_len); - hlen = ipv4::get_pkt_len(p->iph); + hlen = iph->get_hlen() << 2; /* header length sanity check */ - if(hlen < ipv4::hdr_len()) + if(hlen < ip::IP4_HEADER_LEN) { DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Bogus IP header length of %i bytes\n", hlen);); @@ -292,12 +293,12 @@ bool Ipv4Codec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len, } /* test for IP options */ - p->ip_options_len = (uint16_t)(hlen - ipv4::hdr_len()); + p->ip_options_len = (uint16_t)(hlen - ip::IP4_HEADER_LEN); if(p->ip_options_len > 0) { - p->ip_options_data = raw_pkt + ipv4::hdr_len(); - DecodeIPOptions((raw_pkt + ipv4::hdr_len()), p->ip_options_len, p); + p->ip_options_data = raw_pkt + ip::IP4_HEADER_LEN; + DecodeIPOptions((raw_pkt + ip::IP4_HEADER_LEN), p->ip_options_len, p); } else { @@ -425,10 +426,10 @@ static inline void IP4AddrTests (Packet* p) } // check all 32 bits ... - if ( ipv4::is_broadcast(p->iph->ip_src.s_addr) ) + if ( ip::is_broadcast(p->iph->ip_src.s_addr) ) codec_events::decoder_event(p, DECODE_IP4_SRC_BROADCAST); - if ( ipv4::is_broadcast(p->iph->ip_dst.s_addr) ) + if ( ip::is_broadcast(p->iph->ip_dst.s_addr) ) codec_events::decoder_event(p, DECODE_IP4_DST_BROADCAST); /* Loopback traffic - don't use htonl for speed reasons - @@ -441,28 +442,28 @@ static inline void IP4AddrTests (Packet* p) msb_dst = (uint8_t)(p->iph->ip_dst.s_addr & 0xff); #endif // check the msb ... - if ( ipv4::is_loopback(msb_src) || ipv4::is_loopback(msb_dst) ) + if ( ip::is_loopback(msb_src) || ip::is_loopback(msb_dst) ) { codec_events::decoder_event(p, DECODE_BAD_TRAFFIC_LOOPBACK); } // check the msb ... - if ( ipv4::is_this_net(msb_src) ) + if ( ip::is_this_net(msb_src) ) codec_events::decoder_event(p, DECODE_IP4_SRC_THIS_NET); - if ( ipv4::is_this_net(msb_dst) ) + if ( ip::is_this_net(msb_dst) ) codec_events::decoder_event(p, DECODE_IP4_DST_THIS_NET); // check the 'msn' (most significant nibble) ... msb_src >>= 4; msb_dst >>= 4; - if ( ipv4::is_multicast(msb_src) ) + if ( ip::is_multicast(msb_src) ) codec_events::decoder_event(p, DECODE_IP4_SRC_MULTICAST); - if ( ipv4::is_reserved(msb_src) ) + if ( ip::is_reserved(msb_src) ) codec_events::decoder_event(p, DECODE_IP4_SRC_RESERVED); - if ( ipv4::is_reserved(msb_dst)) + if ( ip::is_reserved(msb_dst)) codec_events::decoder_event(p, DECODE_IP4_DST_RESERVED); } @@ -481,7 +482,7 @@ static inline void IPMiscTests(Packet *p) if (p->ip_options[i].data == NULL) continue; - if (ipv4::is_opt_rr(p->ip_options[i].code)) + if (p->ip_options[i].is_opt_rr()) { length = p->ip_options[i].len; if (length < 1) @@ -498,7 +499,7 @@ static inline void IPMiscTests(Packet *p) if (((length + 3) - pointer) % 4) codec_events::decoder_event(p, DECODE_ICMP_DOS_ATTEMPT); } - else if (ipv4::is_opt_ts(p->ip_options[i].code)) + else if (p->ip_options[i].is_opt_ts()) { length = p->ip_options[i].len; if (length < 2) @@ -571,13 +572,13 @@ static void DecodeIPOptions(const uint8_t *start, uint32_t o_len, Packet *p) len_ptr = NULL; } - switch(static_cast(*option_ptr)) + switch(static_cast(*option_ptr)) { - case ipv4::IPOptionCodes::EOL: + case ip::IPOptionCodes::EOL: done = 1; // fall through - case ipv4::IPOptionCodes::NOP: + case ip::IPOptionCodes::NOP: /* if we hit an EOL, we're done */ p->ip_options[opt_count].len = 0; @@ -682,7 +683,7 @@ bool Ipv4Codec::encode(EncState* enc, Buffer* out, const uint8_t* raw_in) /* IPv4 encoded header is hardcoded 20 bytes, we save some * cycles and use the literal header size for checksum */ - ho->ip_csum = checksum::ip_cksum((uint16_t *)ho, ipv4::hdr_len()); + ho->ip_csum = checksum::ip_cksum((uint16_t *)ho, ip::IP4_HEADER_LEN); return true; } @@ -691,7 +692,7 @@ bool Ipv4Codec::update(Packet* p, Layer* lyr, uint32_t* len) IPHdr* h = (IPHdr*)(lyr->start); int i = lyr - p->layers; - *len += ipv4::get_pkt_len(h); + *len += ip::get_pkt_len(h); if ( i + 1 == p->num_layers ) { @@ -702,7 +703,7 @@ bool Ipv4Codec::update(Packet* p, Layer* lyr, uint32_t* len) if ( !PacketWasCooked(p) || (p->packet_flags & PKT_REBUILT_FRAG) ) { h->ip_csum = 0; - h->ip_csum = checksum::ip_cksum((uint16_t *)h, ipv4::get_pkt_len(h)); + h->ip_csum = checksum::ip_cksum((uint16_t *)h, ip::get_pkt_len(h)); } return true; @@ -729,7 +730,7 @@ void Ipv4Codec::format(EncodeFlags f, const Packet* p, Packet* c, Layer* lyr) { lyr->length = sizeof(*ch); ch->ip_len = htons(lyr->length); - ipv4::set_hlen(ch, lyr->length >> 2); + ip::set_hlen(ch, lyr->length >> 2); } } sfiph_build(c, c->iph, AF_INET); diff --git a/src/codecs/ip/cd_ipv6.cc b/src/codecs/ip/cd_ipv6.cc index de0cc0484..f1c5a6084 100644 --- a/src/codecs/ip/cd_ipv6.cc +++ b/src/codecs/ip/cd_ipv6.cc @@ -36,6 +36,7 @@ #include "packet_io/active.h" #include "codecs/ip/cd_ipv6_module.h" #include "codecs/sf_protocols.h" +#include "protocols/protocol_ids.h" namespace { @@ -125,8 +126,8 @@ uint8_t Ipv6Codec::RevTTL (const EncState* enc, uint8_t ttl) void Ipv6Codec::get_protocol_ids(std::vector& v) { - v.push_back(ipv6::ethertype()); - v.push_back(ipv6::prot_id()); + v.push_back(ETHERTYPE_IPV6); + v.push_back(IPPROTO_ID_IPV6); } diff --git a/src/codecs/ip/cd_tcp.cc b/src/codecs/ip/cd_tcp.cc index 8bbf1c80c..b347aeeb9 100644 --- a/src/codecs/ip/cd_tcp.cc +++ b/src/codecs/ip/cd_tcp.cc @@ -123,7 +123,7 @@ bool TcpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len, } /* lay TCP on top of the data cause there is enough of it! */ - p->tcph = reinterpret_cast(const_cast(raw_pkt)); + p->tcph = reinterpret_cast(const_cast(raw_pkt)); /* multiply the payload offset value by 4 */ lyr_len = TCP_OFFSET(p->tcph) << 2; @@ -587,7 +587,7 @@ static inline void TCPMiscTests(Packet *p) bool TcpCodec::encode (EncState* enc, Buffer* out, const uint8_t* raw_in) { int ctl; - const TCPHdr* hi = reinterpret_cast(raw_in); + const tcp::TCPHdr* hi = reinterpret_cast(raw_in); bool attach_payload = (enc->type == EncodeType::ENC_TCP_FIN || enc->type == EncodeType::ENC_TCP_PUSH); @@ -602,7 +602,7 @@ bool TcpCodec::encode (EncState* enc, Buffer* out, const uint8_t* raw_in) if (!update_buffer(out, tcp::get_tcp_hdr_len(hi))) return false; - TCPHdr* ho = reinterpret_cast(out->base); + tcp::TCPHdr* ho = reinterpret_cast(out->base); ctl = (hi->th_flags & TH_SYN) ? 1 : 0; if ( forward(enc) ) @@ -661,7 +661,7 @@ bool TcpCodec::encode (EncState* enc, Buffer* out, const uint8_t* raw_in) ho->th_sum = 0; - if (ipv4::get_version((IPHdr *)enc->ip_hdr) == 4) { + if (ip::get_version((IPHdr *)enc->ip_hdr) == 4) { checksum::Pseudoheader ps; int len = buff_diff(out, (uint8_t*)ho); @@ -688,7 +688,7 @@ bool TcpCodec::encode (EncState* enc, Buffer* out, const uint8_t* raw_in) bool TcpCodec::update(Packet* p, Layer* lyr, uint32_t* len) { - TCPHdr* h = (TCPHdr*)(lyr->start); + tcp::TCPHdr* h = reinterpret_cast(lyr->start); *len += tcp::get_tcp_hdr_len(h) + p->dsize; @@ -719,13 +719,13 @@ bool TcpCodec::update(Packet* p, Layer* lyr, uint32_t* len) void TcpCodec::format(EncodeFlags f, const Packet* p, Packet* c, Layer* lyr) { - TCPHdr* ch = (TCPHdr*)lyr->start; + tcp::TCPHdr* ch = (tcp::TCPHdr*)lyr->start; c->tcph = ch; if ( reverse(f) ) { int i = lyr - c->layers; - TCPHdr* ph = (TCPHdr*)p->layers[i].start; + tcp::TCPHdr* ph = (tcp::TCPHdr*)p->layers[i].start; ch->th_sport = ph->th_dport; ch->th_dport = ph->th_sport; diff --git a/src/codecs/ip/cd_udp.cc b/src/codecs/ip/cd_udp.cc index 4e80b3f19..d4bb941b0 100644 --- a/src/codecs/ip/cd_udp.cc +++ b/src/codecs/ip/cd_udp.cc @@ -36,7 +36,6 @@ #include "protocols/teredo.h" #include "protocols/protocol_ids.h" #include "protocols/icmp4.h" -#include "protocols/icmp6.h" #include "protocols/ipv4.h" #include "protocols/protocol_ids.h" #include "codecs/checksum.h" @@ -341,7 +340,7 @@ bool UdpCodec::encode (EncState* enc, Buffer* out, const uint8_t* raw_in) ho->uh_len = htons((uint16_t)len); ho->uh_chk = 0; - if (ipv4::is_ipv4((ipv4::IPHdr*)enc->ip_hdr)) { + if (ip::is_ipv4(*(enc->ip_hdr))) { checksum::Pseudoheader ps; ps.sip = ((IPHdr *)enc->ip_hdr)->ip_src.s_addr; ps.dip = ((IPHdr *)enc->ip_hdr)->ip_dst.s_addr; @@ -364,20 +363,20 @@ bool UdpCodec::encode (EncState* enc, Buffer* out, const uint8_t* raw_in) } // if this is not GTP, we want to return an ICMP unreachable packet - else if ( ipv4::is_ipv4((ipv4::IPHdr*)enc->ip_hdr)) + else if ( ip::is_ipv4(*(enc->ip_hdr))) { // copied directly from Icmp4Codec::encode() uint8_t* p; IcmpHdr* ho; - if (!update_buffer(out, sizeof(*ho) + enc->ip_len + icmp4::unreach_data())) + if (!update_buffer(out, sizeof(*ho) + enc->ip_len + icmp::unreach_data())) return false; const uint16_t *hi = reinterpret_cast(raw_in); ho = reinterpret_cast(out->base); enc->proto = IPPROTO_ID_ICMPV4; - ho->type = icmp4::IcmpType::DEST_UNREACH; + ho->type = icmp::IcmpType::DEST_UNREACH; ho->code = get_icmp_code(enc->type); ho->cksum = 0; ho->unused = 0; @@ -388,7 +387,7 @@ bool UdpCodec::encode (EncState* enc, Buffer* out, const uint8_t* raw_in) // copy first 8 octets of original ip data (ie udp header) p += enc->ip_len; - memcpy(p, hi, icmp4::unreach_data()); + memcpy(p, hi, icmp::unreach_data()); ho->cksum = checksum::icmp_cksum((uint16_t *)ho, buff_diff(out, (uint8_t *)ho)); } @@ -403,9 +402,9 @@ bool UdpCodec::encode (EncState* enc, Buffer* out, const uint8_t* raw_in) // copy first 8 octets of original ip data (ie udp header) // TBD: copy up to minimum MTU worth of data - if (!update_buffer(out, icmp4::unreach_data())) + if (!update_buffer(out, icmp::unreach_data())) return false; - memcpy(out->base, raw_in, icmp4::unreach_data()); + memcpy(out->base, raw_in, icmp::unreach_data()); // copy original ip header if (!update_buffer(out, enc->ip_len)) diff --git a/src/codecs/link/cd_pppencap.cc b/src/codecs/link/cd_pppencap.cc index 01fc7948d..89c36c6c6 100644 --- a/src/codecs/link/cd_pppencap.cc +++ b/src/codecs/link/cd_pppencap.cc @@ -140,7 +140,7 @@ bool PppEncap::decode(const uint8_t *raw_pkt, const uint32_t& raw_len, case PPP_VJ_UCOMP: /* VJ compression modifies the protocol field. It must be set * to tcp (only TCP packets can be VJ compressed) */ - if(raw_len < (lyr_len + ipv4::hdr_len())) + if(raw_len < (lyr_len + ip::IP4_HEADER_LEN)) { if (ScLogVerbose()) ErrorMessage("PPP VJ min packet length > captured len! " diff --git a/src/codecs/misc/CMakeLists.txt b/src/codecs/misc/CMakeLists.txt index b61902a14..f4ffb17b9 100644 --- a/src/codecs/misc/CMakeLists.txt +++ b/src/codecs/misc/CMakeLists.txt @@ -2,6 +2,9 @@ if(STATIC_CODECS) set(PLUGIN_LIST + cd_ip4_embedded_in_icmp.cc + cd_ip6_embedded_in_icmp.cc + cd_prot_embedded_in_icmp.cc cd_gtp.cc cd_gtp_module.h cd_gtp_module.cc @@ -12,6 +15,9 @@ else(STATIC_CODECS) add_shared_library(cd_gtp codecs cd_gtp.cc cd_gtp_module.h cd_gtp_module.cc) add_shared_library(cd_teredo codecs cd_teredo.cc) + # When static codecs NOT enabled, the icmp files will be included in the + # ICMP libraries in the other file. + endif(STATIC_CODECS) add_library( misc_codecs STATIC diff --git a/src/codecs/misc/cd_gtp.cc b/src/codecs/misc/cd_gtp.cc index a40f00802..d8b8025aa 100644 --- a/src/codecs/misc/cd_gtp.cc +++ b/src/codecs/misc/cd_gtp.cc @@ -215,9 +215,9 @@ bool GtpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len, ip_ver = *(raw_pkt + GTP_MIN_LEN) & 0xF0; if (ip_ver == 0x40) - next_prot_id = ipv4::prot_id(); + next_prot_id = IPPROTO_ID_IPIP; else if (ip_ver == 0x60) - next_prot_id = ipv6::prot_id(); + next_prot_id = IPPROTO_ID_IPV6; } return true; diff --git a/src/codecs/misc/cd_ip4_embedded_in_icmp.cc b/src/codecs/misc/cd_ip4_embedded_in_icmp.cc new file mode 100644 index 000000000..3cb3a47dc --- /dev/null +++ b/src/codecs/misc/cd_ip4_embedded_in_icmp.cc @@ -0,0 +1,221 @@ +/* +** Copyright (C) 2002-2013 Sourcefire, Inc. +** Copyright (C) 1998-2002 Martin Roesch +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License Version 2 as +** published by the Free Software Foundation. You may not use, modify or +** distribute this program under any other version of the GNU General +** Public License. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +// cd_ip4_embedded_in_icmp.cc author Josh Rosenbaum + + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "framework/codec.h" +#include "protocols/ipv4.h" +#include "codecs/decode_module.h" +#include "codecs/codec_events.h" + + +namespace +{ + +// yes, macros are necessary. The API and class constructor require different strings. +// +// this macros is defined in the module to ensure identical names. However, +// if you don't want a module, define the name here. +#ifndef IP4_EMBEDDED_IN_ICMP +#define IP4_EMBEDDED_IN_ICMP "ip4_embedded_in_icmp" +#endif + +class Ip4EmbeddedInIcmpCodec : public Codec +{ +public: + Ip4EmbeddedInIcmpCodec() : Codec(IP4_EMBEDDED_IN_ICMP){}; + ~Ip4EmbeddedInIcmpCodec() {}; + + + virtual bool decode(const uint8_t *raw_pkt, const uint32_t &raw_len, + Packet *, uint16_t &lyr_len, uint16_t &next_prot_id); + + virtual void get_protocol_ids(std::vector&); + +}; + +} // namespace + +// TODO: delete +#include + +void Ip4EmbeddedInIcmpCodec::get_protocol_ids(std::vector& v) +{ + v.push_back(IP_EMBEDDED_IN_ICMP4); +} + +bool Ip4EmbeddedInIcmpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len, + Packet* p, uint16_t& lyr_len, uint16_t& next_prot_id) +{ + uint32_t ip_len; /* length from the start of the ip hdr to the + * pkt end */ + uint32_t hlen; /* ip header length */ + + /* do a little validation */ + if(raw_len < ip::IP4_HEADER_LEN) + { + DEBUG_WRAP(DebugMessage(DEBUG_DECODE, + "ICMP: IP short header (%d bytes)\n", raw_len);); + + codec_events::decoder_event(p, DECODE_ICMP_ORIG_IP_TRUNCATED); + + return false; + } + + /* lay the IP struct over the raw data */ + const IPHdr *ip4h = reinterpret_cast(raw_pkt); + + /* + * with datalink DLT_RAW it's impossible to differ ARP datagrams from IP. + * So we are just ignoring non IP datagrams + */ + if((ip4h->get_ver() != 4) && !IS_IP6(p)) + { + DEBUG_WRAP(DebugMessage(DEBUG_DECODE, + "ICMP: not IPv4 datagram ([ver: 0x%x][len: 0x%x])\n", + ip4h->get_ver(), ntohs(ip4h->get_len()));); + + codec_events::decoder_event(p, DECODE_ICMP_ORIG_IP_VER_MISMATCH); + + return false; + } + + ip_len = ntohs(ip4h->get_len());/* set the IP datagram length */ + hlen = ip4h->get_len() << 2; /* set the IP header length */ + + if(raw_len < hlen) + { + DEBUG_WRAP(DebugMessage(DEBUG_DECODE, + "ICMP: IP len (%d bytes) < IP hdr len (%d bytes), packet discarded\n", + ip_len, hlen);); + + codec_events::decoder_event(p, DECODE_ICMP_ORIG_DGRAM_LT_ORIG_IP); + return false; + } + + /* set the remaining packet length */ + ip_len = raw_len - hlen; + + uint16_t orig_frag_offset = ntohs(ip4h->get_off()); + orig_frag_offset &= 0x1FFF; + + if (orig_frag_offset == 0) + { + /* Original IP payload should be 64 bits */ + if (ip_len < 8) + { + codec_events::decoder_event(p, DECODE_ICMP_ORIG_PAYLOAD_LT_64); + + return false; + } + /* ICMP error packets could contain as much of original payload + * as possible, but not exceed 576 bytes + */ + else if (ntohs(GET_IPH_LEN(p)) > 576) + { + codec_events::decoder_event(p, DECODE_ICMP_ORIG_PAYLOAD_GT_576); + } + } + else + { + /* RFC states that only first frag will get an ICMP response */ + codec_events::decoder_event(p, DECODE_ICMP_ORIG_IP_WITH_FRAGOFFSET); + return false; + } + + DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "ICMP Unreachable IP header length: " + "%lu\n", (unsigned long)hlen);); + + // since we know the protocol ID in this layer (and NOT the + // next layer), set the correct protocol here. Normally, + // I would just set the next_protocol_id and let the packet_manger + // decode the next layer. However, I can't set the next_prot_id in + // this case because I don't want this going to the TCP, UDP, or + // ICMP codec. Therefore, doing a minor decode here. + switch(ip4h->get_proto()) + { + case IPPROTO_TCP: /* decode the interesting part of the header */ + p->proto_bits |= PROTO_BIT__TCP_EMBED_ICMP; + next_prot_id = PROT_EMBEDDED_IN_ICMP; + break; + + case IPPROTO_UDP: + p->proto_bits |= PROTO_BIT__UDP_EMBED_ICMP; + next_prot_id = PROT_EMBEDDED_IN_ICMP; + break; + + case IPPROTO_ICMP: + p->proto_bits |= PROTO_BIT__ICMP_EMBED_ICMP; + next_prot_id = PROT_EMBEDDED_IN_ICMP; + break; + } + + return true; +} + +//------------------------------------------------------------------------- +// api +//------------------------------------------------------------------------- + + +static Codec* ctor(Module*) +{ + return new Ip4EmbeddedInIcmpCodec(); +} + +static void dtor(Codec *cd) +{ + delete cd; +} + + +static const CodecApi ip4_embedded_in_icmp_api = +{ + { + PT_CODEC, + IP4_EMBEDDED_IN_ICMP, + CDAPI_PLUGIN_V0, + 0, + nullptr, // module constructor + nullptr // module destructor + }, + nullptr, // g_ctor + nullptr, // g_dtor + nullptr, // t_ctor + nullptr, // t_dtor + ctor, + dtor, +}; + + +#ifdef BUILDING_SO +SO_PUBLIC const BaseApi* snort_plugins[] = +{ + &name_api.base, + nullptr +}; +#else +const BaseApi* cd_ip4_embedded_in_icmp = &ip4_embedded_in_icmp_api.base; +#endif diff --git a/src/codecs/misc/cd_ip6_embedded_in_icmp.cc b/src/codecs/misc/cd_ip6_embedded_in_icmp.cc new file mode 100644 index 000000000..27cbc3442 --- /dev/null +++ b/src/codecs/misc/cd_ip6_embedded_in_icmp.cc @@ -0,0 +1,193 @@ +/* +** Copyright (C) 2002-2013 Sourcefire, Inc. +** Copyright (C) 1998-2002 Martin Roesch +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License Version 2 as +** published by the Free Software Foundation. You may not use, modify or +** distribute this program under any other version of the GNU General +** Public License. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +// cd_ip6_embedded_in_icmp.cc author Josh Rosenbaum + + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "framework/codec.h" +#include "protocols/ipv4.h" +#include "codecs/decode_module.h" +#include "codecs/codec_events.h" + + +namespace +{ + +// yes, macros are necessary. The API and class constructor require different strings. +// +// this macros is defined in the module to ensure identical names. However, +// if you don't want a module, define the name here. +#ifndef IP6_EMBEDDED_IN_ICMP +#define IP6_EMBEDDED_IN_ICMP "ip6_embedded_in_icmp" +#endif + +class Ip6EmbeddedInIcmpCodec : public Codec +{ +public: + Ip6EmbeddedInIcmpCodec() : Codec(IP6_EMBEDDED_IN_ICMP){}; + ~Ip6EmbeddedInIcmpCodec() {}; + + + virtual void get_protocol_ids(std::vector&); + virtual bool decode(const uint8_t *raw_pkt, const uint32_t &raw_len, + Packet *, uint16_t &lyr_len, uint16_t &next_prot_id); +}; + +} // namespace + +// TODO: delete +#include + +void Ip6EmbeddedInIcmpCodec::get_protocol_ids(std::vector& v) +{ + v.push_back(IP_EMBEDDED_IN_ICMP6); +} + +bool Ip6EmbeddedInIcmpCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len, + Packet* p, uint16_t& lyr_len, uint16_t& next_prot_id) +{ +// uint16_t orig_frag_offset; + + /* lay the IP struct over the raw data */ + const ipv6::IP6RawHdr* ip6h = reinterpret_cast(raw_pkt); + + DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "DecodeICMPEmbeddedIP6: ip header" + " starts at: %p, length is %lu\n", ip6h, + (unsigned long) raw_len);); + + /* do a little validation */ + if ( raw_len < ipv6::hdr_len() ) + { + DEBUG_WRAP(DebugMessage(DEBUG_DECODE, + "ICMP6: IP short header (%d bytes)\n", raw_len);); + + codec_events::decoder_event(p, DECODE_ICMP_ORIG_IP_TRUNCATED); + + return false; + } + + /* + * with datalink DLT_RAW it's impossible to differ ARP datagrams from IP. + * So we are just ignoring non IP datagrams + */ + if(ip6h->get_ver() != 6) + { + DEBUG_WRAP(DebugMessage(DEBUG_DECODE, + "ICMP: not IPv6 datagram ([ver: 0x%x][len: 0x%x])\n", + ip6h->get_ver(), raw_len);); + + codec_events::decoder_event(p, DECODE_ICMP_ORIG_IP_VER_MISMATCH); + + return false; + } + + if ( raw_len < ipv6::hdr_len() ) + { + DEBUG_WRAP(DebugMessage(DEBUG_DECODE, + "ICMP6: IP6 len (%d bytes) < IP6 hdr len (%d bytes), packet discarded\n", + raw_len, ipv6::hdr_len());); + + codec_events::decoder_event(p, DECODE_ICMP_ORIG_DGRAM_LT_ORIG_IP); + + return false; + } + +// orig_frag_offset = ntohs(GET_ORIG_IPH_OFF(p)); +// orig_frag_offset &= 0x1FFF; + + // XXX NOT YET IMPLEMENTED - fragments inside ICMP payload + + DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "ICMP6 Unreachable IP6 header length: " + "%lu\n", (unsigned long)ipv6::hdr_len());); + + // since we know the protocol ID in this layer (and NOT the + // next layer), set the correct protocol here. Normally, + // I would just set the next_protocol_id and let the packet_manger + // decode the next layer. However, I can't set the next_prot_id in + // this case because I don't want this going to the TCP, UDP, or + // ICMP codec. Therefore, doing a minor decode here. + switch(ip6h->get_next()) + { + case IPPROTO_TCP: /* decode the interesting part of the header */ + p->proto_bits |= PROTO_BIT__TCP_EMBED_ICMP; + next_prot_id = PROT_EMBEDDED_IN_ICMP; + break; + + case IPPROTO_UDP: + p->proto_bits |= PROTO_BIT__UDP_EMBED_ICMP; + next_prot_id = PROT_EMBEDDED_IN_ICMP; + break; + + case IPPROTO_ICMP: + p->proto_bits |= PROTO_BIT__ICMP_EMBED_ICMP; + next_prot_id = PROT_EMBEDDED_IN_ICMP; + break; + } + + return true; +} + +//------------------------------------------------------------------------- +// api +//------------------------------------------------------------------------- + +static Codec* ctor(Module*) +{ + return new Ip6EmbeddedInIcmpCodec(); +} + +static void dtor(Codec *cd) +{ + delete cd; +} + + +static const CodecApi ip6_embedded_in_icmp_api = +{ + { + PT_CODEC, + IP6_EMBEDDED_IN_ICMP, + CDAPI_PLUGIN_V0, + 0, + nullptr, // module constructor + nullptr // module destructor + }, + nullptr, // g_ctor + nullptr, // g_dtor + nullptr, // t_ctor + nullptr, // t_dtor + ctor, + dtor, +}; + + +#ifdef BUILDING_SO +SO_PUBLIC const BaseApi* snort_plugins[] = +{ + &name_api.base, + nullptr +}; +#else +const BaseApi* cd_ip6_embedded_in_icmp = &ip6_embedded_in_icmp_api.base; +#endif diff --git a/src/codecs/misc/cd_prot_embedded_in_icmp.cc b/src/codecs/misc/cd_prot_embedded_in_icmp.cc new file mode 100644 index 000000000..c81863619 --- /dev/null +++ b/src/codecs/misc/cd_prot_embedded_in_icmp.cc @@ -0,0 +1,120 @@ +/* +** Copyright (C) 2002-2013 Sourcefire, Inc. +** Copyright (C) 1998-2002 Martin Roesch +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License Version 2 as +** published by the Free Software Foundation. You may not use, modify or +** distribute this program under any other version of the GNU General +** Public License. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +// cd_prot_embedded_in_icmp.cc author Josh Rosenbaum + + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "framework/codec.h" + + +namespace +{ + +// yes, macros are necessary. The API and class constructor require different strings. +// +// this macros is defined in the module to ensure identical names. However, +// if you don't want a module, define the name here. +#ifndef ProtEmbeddedInIcmp_NAME +#define ProtEmbeddedInIcmp_NAME "prot_embedded_in_icmp" +#endif + +class ProtEmbeddedInIcmp : public Codec +{ +public: + ProtEmbeddedInIcmp() : Codec(ProtEmbeddedInIcmp_NAME){}; + ~ProtEmbeddedInIcmp() {}; + + + virtual bool decode(const uint8_t *raw_pkt, const uint32_t &raw_len, + Packet *, uint16_t &lyr_len, uint16_t &next_prot_id); + + virtual void get_protocol_ids(std::vector&); +}; + +} // namespace + + +void ProtEmbeddedInIcmp::get_protocol_ids(std::vector& v) +{ + v.push_back(PROT_EMBEDDED_IN_ICMP); +} + +bool ProtEmbeddedInIcmp::decode(const uint8_t* /*raw_pkt*/, const uint32_t& /*raw_len*/, + Packet* /*p*/, uint16_t& /*lyr_len*/, uint16_t& /*next_prot_id*/) +{ + + // Since the previous layer already set the correct p->proto_bits, + // there is really nothing to do here. This layer is actually + // a placeholder so I can easily find this layer's data at some + // other point in Snort++. + return true; +} + + + + +//------------------------------------------------------------------------- +// api +//------------------------------------------------------------------------- + + +static Codec* ctor(Module*) +{ + return new ProtEmbeddedInIcmp(); +} + +static void dtor(Codec *cd) +{ + delete cd; +} + + +static const CodecApi prot_embedded_in_icmp_api = +{ + { + PT_CODEC, + ProtEmbeddedInIcmp_NAME, + CDAPI_PLUGIN_V0, + 0, + nullptr, + nullptr + }, + nullptr, // ginit + nullptr, // gterm + nullptr, // tinit + nullptr, // tterm + ctor, + dtor, +}; + + +#ifdef BUILDING_SO +SO_PUBLIC const BaseApi* snort_plugins[] = +{ + &prot_embedded_in_icmp_api.base, + nullptr +}; +#else +const BaseApi* cd_prot_embedded_in_icmp = &prot_embedded_in_icmp_api.base; +#endif diff --git a/src/codecs/root/CMakeLists.txt b/src/codecs/root/CMakeLists.txt index 1c9936c60..c37f85798 100644 --- a/src/codecs/root/CMakeLists.txt +++ b/src/codecs/root/CMakeLists.txt @@ -7,6 +7,7 @@ if (STATIC_CODECS) if (ENABLE_NON_ETHER_DECODERS) set(NON_ETHER_PLUGINS cd_linux_sll.cc + cd_ppp.cc cd_wlan.cc cd_wlan_module.h cd_wlan_module.cc @@ -15,7 +16,6 @@ if (STATIC_CODECS) # root_i4lrawip.cc # root_oldpflog.cc # root_enc.cc - # root_ppp.cc # root_pflog.cc # root_pppserial.cc # root_chdlc.cc @@ -30,6 +30,7 @@ else(STATIC_CODECS) if (ENABLE_NON_ETHER_DECODERS) add_shared_library(cd_wlan codecs cd_wlan.cc cd_wlan_module.h cd_wlan_module.cc) add_shared_library(cd_linux_sll codecs cd_linux_sll.cc) + add_shared_library(cd_ppp codecs cd_ppp.cc) endif(ENABLE_NON_ETHER_DECODERS) endif(STATIC_CODECS) diff --git a/src/codecs/root/Makefile.am b/src/codecs/root/Makefile.am index 90e484b11..3b396979a 100644 --- a/src/codecs/root/Makefile.am +++ b/src/codecs/root/Makefile.am @@ -15,6 +15,7 @@ if ENABLE_NON_ETHER_DECODER if STATIC_CODECS libroot_codecs_a_SOURCES += \ cd_linux_sll.cc \ +cd_ppp.cc \ cd_wlan.cc \ cd_wlan_module.h \ cd_wlan_module.cc @@ -34,16 +35,21 @@ cd_wlan_module.cc else ehlibdir = $(pkglibdir)/codecs -ehlib_LTLIBRARIES = libcd_wlan.la -libcd_wlan_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO -libcd_wlan_la_LDFLAGS = -export-dynamic -shared -libcd_wlan_la_SOURCES = cd_wlan.cc cd_wlan_module.h cd_wlan_module.cc - -ehlib_LTLIBRARIES += libcd_linux_sll.la +ehlib_LTLIBRARIES = libcd_linux_sll.la libcd_linux_sll_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO libcd_linux_sll_la_LDFLAGS = -export-dynamic -shared libcd_linux_sll_la_SOURCES = cd_linux_sll.cc +ehlib_LTLIBRARIES += libcd_ppp.la +libcd_ppp_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO +libcd_ppp_la_LDFLAGS = -export-dynamic -shared +libcd_ppp_la_SOURCES = cd_ppp.cc cd_ppp.h + +ehlib_LTLIBRARIES += libcd_wlan.la +libcd_wlan_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO +libcd_wlan_la_LDFLAGS = -export-dynamic -shared +libcd_wlan_la_SOURCES = cd_wlan.cc cd_wlan_module.h cd_wlan_module.cc + endif endif diff --git a/src/codecs/root/cd_ppp.cc b/src/codecs/root/cd_ppp.cc new file mode 100644 index 000000000..b4ea96b6a --- /dev/null +++ b/src/codecs/root/cd_ppp.cc @@ -0,0 +1,144 @@ +/* $Id: decode.c,v 1.285 2013-06-29 03:03:00 rcombs Exp $ */ + +/* +** Copyright (C) 2002-2013 Sourcefire, Inc. +** Copyright (C) 1998-2002 Martin Roesch +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License Version 2 as +** published by the Free Software Foundation. You may not use, modify or +** distribute this program under any other version of the GNU General +** Public License. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "framework/codec.h" +#include "main/snort.h" + + + +namespace +{ + +// yes, macros are necessary. The API and class constructor require different strings. +// +// this macros is defined in the module to ensure identical names. However, +// if you don't want a module, define the name here. +#ifndef PPP_NAME +#define PPP_NAME "point_to_point" +#endif + +class PPPCodec : public Codec +{ +public: + PPPCodec() : Codec(PPP_NAME){} + ~PPPCodec() {} + + + virtual bool decode(const uint8_t *raw_pkt, const uint32_t &raw_len, + Packet *, uint16_t &lyr_len, uint16_t &next_prot_id); + virtual void get_data_link_type(std::vector&); +}; + +} // namespace + + +#ifndef DLT_PPP +static constexpr int DLT_PPP = 51; +#endif + +static constexpr uint8_t CHDLC_ADDR_BROADCAST = 0xff; +static constexpr uint8_t CHDLC_CTRL_UNNUMBERED = 0x03; + + +void PPPCodec::get_data_link_type(std::vector& v) +{ + v.push_back(DLT_PPP); +} + + +bool PPPCodec::decode(const uint8_t *raw_pkt, const uint32_t& raw_len, + Packet* /*p*/, uint16_t& lyr_len, uint16_t& next_prot_id) +{ + if(raw_len < 2) + { + if (ScLogVerbose()) + { + ErrorMessage("Length not big enough for even a single " + "header or a one byte payload\n"); + } + return false; + } + + if(raw_pkt[0] == CHDLC_ADDR_BROADCAST && raw_pkt[1] == CHDLC_CTRL_UNNUMBERED) + { + /* + * Check for full HDLC header (rfc1662 section 3.2) + */ + lyr_len = 2; + } + + next_prot_id = ETHERTYPE_PPP; + return true; +} + + + +//------------------------------------------------------------------------- +// api +//------------------------------------------------------------------------- + + +static Codec* ctor(Module*) +{ + return new PPPCodec(); +} + +static void dtor(Codec *cd) +{ + delete cd; +} + + +static const CodecApi ppp_api = +{ + { + PT_CODEC, + PPP_NAME, + CDAPI_PLUGIN_V0, + 0, + nullptr, // mod_ctor + nullptr, // mod_dtor + }, + nullptr, // pinit + nullptr, // pterm + nullptr, // tinit + nullptr, // tterm + ctor, + dtor, +}; + + +#ifdef BUILDING_SO +SO_PUBLIC const BaseApi* snort_plugins[] = +{ + &ppp_api.base, + nullptr +}; +#else +const BaseApi* cd_ppp = &ppp_api.base; +#endif + diff --git a/src/codecs/root/root_ppp.cc b/src/codecs/root/root_ppp.cc deleted file mode 100644 index 40564407b..000000000 --- a/src/codecs/root/root_ppp.cc +++ /dev/null @@ -1,82 +0,0 @@ -/* $Id: decode.c,v 1.285 2013-06-29 03:03:00 rcombs Exp $ */ - -/* -** Copyright (C) 2002-2013 Sourcefire, Inc. -** Copyright (C) 1998-2002 Martin Roesch -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License Version 2 as -** published by the Free Software Foundation. You may not use, modify or -** distribute this program under any other version of the GNU General -** Public License. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - - -#include "framework/codec.h" - - -static int DLT_PPP = 51; - - -/* - * Function: DecodePppPkt(Packet *, char *, DAQ_PktHdr_t*, uint8_t*) - * - * Purpose: Decode PPP traffic (either RFC1661 or RFC1662 framing). - * This really is intended to handle IPCP - * - * Arguments: p => pointer to decoded packet struct - * user => Utility pointer, unused - * pkthdr => ptr to the packet header - * pkt => pointer to the real live packet data - * - * Returns: void function - */ -// DecodePppPkt() and DecodePppSerialPkt() may be incorrect ... -// both skip past 2 byte protocol and then call DecodePppPktEncapsulated() -// which does the same thing. That one works inside DecodePPPoEPkt(); -void DecodePppPkt(Packet * p, const DAQ_PktHdr_t * pkthdr, const uint8_t * pkt) -{ - uint32_t cap_len = pkthdr->caplen; - int hlen = 0; - - if(cap_len < 2) - { - if (ScLogVerbose()) - { - ErrorMessage("Length not big enough for even a single " - "header or a one byte payload\n"); - } - MODULE_PROFILE_END(decodePerfStats); - return; - } - - if(pkt[0] == CHDLC_ADDR_BROADCAST && pkt[1] == CHDLC_CTRL_UNNUMBERED) - { - /* - * Check for full HDLC header (rfc1662 section 3.2) - */ - hlen = 2; - } - - DecodePppPktEncapsulated(p->pkt + hlen, cap_len - hlen, p); - - MODULE_PROFILE_END(decodePerfStats); - return; -} - - diff --git a/src/codecs/root/root_ppp.h b/src/codecs/root/root_ppp.h deleted file mode 100644 index a68caebf9..000000000 --- a/src/codecs/root/root_ppp.h +++ /dev/null @@ -1,29 +0,0 @@ -/* -** Copyright (C) 2002-2013 Sourcefire, Inc. -** Copyright (C) 1998-2002 Martin Roesch -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License Version 2 as -** published by the Free Software Foundation. You may not use, modify or -** distribute this program under any other version of the GNU General -** Public License. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - - -#ifndef ROOT_PPP_H -#define ROOT_PPP_H - - -void DecodePppPkt(Packet *, const DAQ_PktHdr_t*, const uint8_t *); - -#endif /* ROOT_PPP_H */ - diff --git a/src/detection/detect.cc b/src/detection/detect.cc index 62c2345cf..0cfeb5b3a 100644 --- a/src/detection/detect.cc +++ b/src/detection/detect.cc @@ -308,7 +308,8 @@ int Detect(Packet * p) return 0; } - + // FIXIT: Bug?? Do we want to check inner IP protocol tpe, + // when indexing outer ip array?? if (!snort_conf->ip_proto_array[GET_IPH_PROTO(p)]) { switch (p->outer_family) diff --git a/src/events/event_queue.cc b/src/events/event_queue.cc index 719ef1d87..949957aca 100644 --- a/src/events/event_queue.cc +++ b/src/events/event_queue.cc @@ -157,7 +157,7 @@ int SnortEventqAdd(uint32_t gid, uint32_t sid, RuleType type) EventNode* en = (EventNode*)sfeventq_event_alloc(event_queue[qIndex]); - if ( en ) + if ( !en ) return -1; en->otn = otn; diff --git a/src/flow/flow_key.cc b/src/flow/flow_key.cc index bf38ca746..464b0e907 100644 --- a/src/flow/flow_key.cc +++ b/src/flow/flow_key.cc @@ -1,4 +1,3 @@ - /* ** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. ** Copyright (C) 2005-2013 Sourcefire, Inc. @@ -89,7 +88,7 @@ inline void FlowKey::init4( port_h = srcPort; } if (ScMplsOverlappingIp() && - ipv4::isPrivateIP(*src) && ipv4::isPrivateIP(*dst)) + ip::isPrivateIP(*src) && ip::isPrivateIP(*dst)) mplsLabel = mplsId; else mplsLabel = 0; diff --git a/src/framework/codec.h b/src/framework/codec.h index 21f46a5fa..2332cae55 100644 --- a/src/framework/codec.h +++ b/src/framework/codec.h @@ -96,6 +96,7 @@ static inline bool update_buffer(Buffer* buf, size_t n) } + class Codec { public: @@ -115,8 +116,6 @@ public: // Get the codec's name inline const char* get_name(){return name; }; - // Several codecs are for convenience. So, tell Snort++ not to print any info - virtual bool dump_at_startup(){ return true; }; // used for backwards compatability. virtual PROTO_ID get_proto_id() { return PROTO_AH; }; // Registers this Codec's data link type (as defined by libpcap) @@ -173,14 +172,14 @@ protected: return (((uint8_t*)(buf->base+buf->end))-(uint8_t*)ho); } - static inline icmp4::IcmpCode get_icmp_code (EncodeType et) + static inline icmp::IcmpCode get_icmp_code (EncodeType et) { switch ( et ) { - case EncodeType::ENC_UNR_NET: return icmp4::IcmpCode::NET_UNREACH; - case EncodeType::ENC_UNR_HOST: return icmp4::IcmpCode::HOST_UNREACH; - case EncodeType::ENC_UNR_PORT: return icmp4::IcmpCode::PORT_UNREACH; - case EncodeType::ENC_UNR_FW: return icmp4::IcmpCode::PKT_FILTERED; - default: return icmp4::IcmpCode::PORT_UNREACH; + case EncodeType::ENC_UNR_NET: return icmp::IcmpCode::NET_UNREACH; + case EncodeType::ENC_UNR_HOST: return icmp::IcmpCode::HOST_UNREACH; + case EncodeType::ENC_UNR_PORT: return icmp::IcmpCode::PORT_UNREACH; + case EncodeType::ENC_UNR_FW: return icmp::IcmpCode::PKT_FILTERED; + default: return icmp::IcmpCode::PORT_UNREACH; } } diff --git a/src/log/log_text.cc b/src/log/log_text.cc index 5f810d06c..8febed432 100644 --- a/src/log/log_text.cc +++ b/src/log/log_text.cc @@ -1004,7 +1004,6 @@ static void LogICMPEmbeddedIP(TextLog* log, Packet *p) { Packet op; Packet *orig_p; - uint32_t orig_ip_hlen; if (log == NULL || p == NULL) return; @@ -1012,50 +1011,73 @@ static void LogICMPEmbeddedIP(TextLog* log, Packet *p) memset((char*)&op, 0, sizeof(op)); orig_p = &op; - orig_p->iph = p->orig_iph; - orig_p->tcph = p->orig_tcph; - orig_p->udph = p->orig_udph; - orig_p->sp = p->orig_sp; - orig_p->dp = p->orig_dp; - orig_p->icmph = p->orig_icmph; - orig_p->iph_api = p->orig_iph_api; -// orig_p->ip4h = p->orig_ip4h; -// orig_p->ip6h = p->orig_ip6h; - orig_p->family = p->orig_family; - - if(orig_p->iph != NULL) + if (!layer::set_api_ip_embed_icmp(p, op.ip_api)) { - TextLog_Print(log, "\n** ORIGINAL DATAGRAM DUMP:\n"); - LogIPHeader(log, orig_p); - orig_ip_hlen = ipv4::get_pkt_len(p->orig_iph) << 2; - - switch(GET_IPH_PROTO(orig_p)) + switch(orig_p->ip_api.proto()) { case IPPROTO_TCP: - if(orig_p->tcph != NULL) + { + const tcp::TCPHdr* tcph = layer::get_tcp_embed_icmp(p); + if (tcph) + { + orig_p->sp = ntohs(tcph->th_sport); + orig_p->dp = ntohs(tcph->th_dport); + orig_p->tcph = tcph; + } + + TextLog_Print(log, "\n** ORIGINAL DATAGRAM DUMP:\n"); + LogIPHeader(log, orig_p); + + if(tcph != NULL) + { TextLog_Print(log, "Seq: 0x%lX\n", (u_long)ntohl(orig_p->tcph->th_seq)); + } break; + } case IPPROTO_UDP: - if(orig_p->udph != NULL) + { + const udp::UDPHdr* udph = layer::get_udp_embed_icmp(p); + if (udph) + { + orig_p->sp = ntohs(p->udph->uh_sport); + orig_p->dp = ntohs(p->udph->uh_dport); + orig_p->udph = udph; + } + + TextLog_Print(log, "\n** ORIGINAL DATAGRAM DUMP:\n"); + LogIPHeader(log, orig_p); + + if(udph != NULL) TextLog_Print(log, "Len: %d Csum: %d\n", ntohs(orig_p->udph->uh_len) - UDP_HEADER_LEN, ntohs(orig_p->udph->uh_chk)); break; + } case IPPROTO_ICMP: - if(orig_p->icmph != NULL) - LogEmbeddedICMPHeader(log, orig_p->icmph); + { + TextLog_Print(log, "\n** ORIGINAL DATAGRAM DUMP:\n"); + LogIPHeader(log, orig_p); + + const icmp::ICMPHdr* icmph = layer::get_icmp_embed_icmp(p); + if(icmph != NULL) + LogEmbeddedICMPHeader(log, icmph); break; + } default: + TextLog_Print(log, "\n** ORIGINAL DATAGRAM DUMP:\n"); + LogIPHeader(log, orig_p); + TextLog_Print(log, "Protocol: 0x%X (unknown or " "header truncated)", GET_IPH_PROTO(orig_p)); break; } /* switch */ /* if more than 8 bytes of original IP payload sent */ + uint32_t orig_ip_hlen = p->ip_api.hlen() << 2; if (p->dsize - orig_ip_hlen > 8) { TextLog_Print(log, "(%d more bytes of original packet)\n", diff --git a/src/main/snort_config.cc b/src/main/snort_config.cc index ff73f936b..4ad8fbe60 100644 --- a/src/main/snort_config.cc +++ b/src/main/snort_config.cc @@ -195,6 +195,8 @@ SnortConfig * SnortConfNew(void) set_ips_policy(sc->get_ips_policy()); set_network_policy(sc->get_network_policy()); + sc->max_encapsulations = -1; + return sc; } @@ -465,6 +467,9 @@ SnortConfig * MergeSnortConfs(SnortConfig *cmd_line, SnortConfig *config_file) if ( cmd_line->remote_control ) config_file->remote_control = cmd_line->remote_control; + if ( cmd_line->max_encapsulations ) + config_file->max_encapsulations = cmd_line->max_encapsulations; + // config file vars are stored differently // FIXIT should config_file and cmd_line use the same var list / table? config_file->var_list = NULL; diff --git a/src/managers/packet_manager.cc b/src/managers/packet_manager.cc index 6c0e7cfe0..5187c02e7 100644 --- a/src/managers/packet_manager.cc +++ b/src/managers/packet_manager.cc @@ -160,8 +160,8 @@ static const uint8_t* encode_packet( enc->p = p; enc->ip_hdr = p->layers[layer::get_inner_ip_lyr(p)].start; - if ( ipv4::is_ipv4(*(enc->ip_hdr))) - enc->ip_len = ipv4::get_pkt_len((IPHdr*) enc->ip_hdr); + if ( ip::is_ipv4(*(enc->ip_hdr))) + enc->ip_len = ip::get_pkt_len((IPHdr*) enc->ip_hdr); else if ( ipv6::is_ip6_hdr_ver((ipv6::IP6RawHdr*)(enc->ip_hdr))) enc->ip_len = sizeof(ipv6::IP6RawHdr); else @@ -207,7 +207,7 @@ static bool api_instantiated(const CodecApi* cd_api) std::find(s_codecs.begin(), s_codecs.end(), cd_api); if (p == s_codecs.end()) - FatalError("PacketManager:: should never reach this code!!" \ + FatalError("PacketManager:: should never reach this code!!" "Cannot find Codec %s's api", cd_api->base.name); int pos = p - s_codecs.begin(); @@ -409,6 +409,8 @@ void PacketManager::decode( // initialize all of the relevent data to decode this packet memset(p, 0, PKT_ZERO_LEN); + p->ip_api.reset(); + p->pkth = pkthdr; p->pkt = pkt; len = pkthdr->caplen; @@ -418,6 +420,11 @@ void PacketManager::decode( // loop until the protocol id is no longer valid while(s_protocols[mapped_prot]->decode(pkt, len, p, lyr_len, prot_id)) { + DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Codec %s (protocol_id: %u:" + "ip header starts at: %p, length is %lu\n", + s_protocols[mapped_prot]->get_name(), prot_id, pkt, + (unsigned long) len);); + // must be done here after decode and before push for case layer // LAYER_MAX+1 is invalid or the default codec if ( p->num_layers == LAYER_MAX ) @@ -440,6 +447,12 @@ void PacketManager::decode( lyr_len = 0; } + DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "Codec %s (protocol_id: %hu: ip header" + " starts at: %p, length is %lu\n", + s_protocols[mapped_prot]->get_name(), + prot_id, pkt, (unsigned long) len);); + + // if the final protocol ID is not the default codec, a Codec failed if (prev_prot_id != FINISHED_DECODE) { @@ -452,7 +465,7 @@ void PacketManager::decode( s_stats[other_codecs]++; } - if (p->decode_flags & DECODE__ESP) + if (p->decode_flags & DECODE__TRUST_ON_FAIL) p->packet_flags |= PKT_TRUST; } diff --git a/src/managers/packet_manager.h b/src/managers/packet_manager.h index 70df31d13..3dcda9011 100644 --- a/src/managers/packet_manager.h +++ b/src/managers/packet_manager.h @@ -126,8 +126,6 @@ public: { encode_set_pkt(NULL); } - }; #endif - diff --git a/src/network_inspectors/binder/binder.cc b/src/network_inspectors/binder/binder.cc index 60a3ebfdc..0124cf417 100644 --- a/src/network_inspectors/binder/binder.cc +++ b/src/network_inspectors/binder/binder.cc @@ -176,7 +176,9 @@ int Binder::check_rules(Flow* flow, Packet* p) unsigned i, sz = bindings.size(); Port port = (p->packet_flags & PKT_FROM_CLIENT) ? p->dp : p->sp; - uint16_t vlan = vlan::vth_vlan(layer::get_vlan_layer(p)); + + if (p->proto_bits & PROTO_BIT__VLAN) + uint16_t vlan = vlan::vth_vlan(layer::get_vlan_layer(p)); for ( i = 0; i < sz; i++ ) { diff --git a/src/network_inspectors/normalize/norm.cc b/src/network_inspectors/normalize/norm.cc index 4bd82f731..f2c4ebb8e 100644 --- a/src/network_inspectors/normalize/norm.cc +++ b/src/network_inspectors/normalize/norm.cc @@ -1,6 +1,6 @@ /**************************************************************************** * -** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. + * Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. * Copyright (C) 2005-2013 Sourcefire, Inc. * * This program is free software; you can redistribute it and/or modify @@ -220,10 +220,10 @@ static int Norm_IP4 ( changes++; } } - if ( p->layers[layer].length > IP_HEADER_LEN ) + if ( p->layers[layer].length > ip::IP4_HEADER_LEN ) { - uint8_t* opts = p->layers[layer].start + IP_HEADER_LEN; - uint8_t len = p->layers[layer].length - IP_HEADER_LEN; + uint8_t* opts = p->layers[layer].start + ip::IP4_HEADER_LEN; + uint8_t len = p->layers[layer].length - ip::IP4_HEADER_LEN; // expect len > 0 because IHL yields a multiple of 4 memset(opts, IPOPT_NOP, len); normStats[PC_IP4_OPTS]++; @@ -241,9 +241,9 @@ static int Norm_ICMP4 ( ICMPHdr* h = (ICMPHdr*)(p->layers[layer].start); if ( (h->type == ICMP_ECHO || h->type == ICMP_ECHOREPLY) && - (h->code != icmp4::IcmpCode::ECHO_CODE) ) + (h->code != icmp::IcmpCode::ECHO_CODE) ) { - h->code = icmp4::IcmpCode::ECHO_CODE; + h->code = icmp::IcmpCode::ECHO_CODE; normStats[PC_ICMP4_ECHO]++; sfBase.iPegs[PERF_COUNT_ICMP4_ECHO]++; changes++; @@ -283,7 +283,7 @@ static int Norm_ICMP6 ( (uint16_t)h->type == icmp6::Icmp6Types::REPLY) && (h->code != 0) ) { - h->code = static_cast(0); + h->code = static_cast(0); normStats[PC_ICMP6_ECHO]++; sfBase.iPegs[PERF_COUNT_ICMP6_ECHO]++; changes++; @@ -344,7 +344,7 @@ static inline void NopDaOpt (uint8_t* opt, uint8_t len) static inline int Norm_TCPOptions ( NormalizerConfig* config, - uint8_t* opts, size_t len, const TCPHdr* h, uint8_t numOpts, int changes) + uint8_t* opts, size_t len, const tcp::TCPHdr* h, uint8_t numOpts, int changes) { size_t i = 0; uint8_t c = 0; @@ -433,7 +433,7 @@ static inline int Norm_TCPPadding ( static int Norm_TCP ( NormalizerConfig* c, Packet * p, uint8_t layer, int changes) { - TCPHdr* h = (TCPHdr*)(p->layers[layer].start); + tcp::TCPHdr* h = (tcp::TCPHdr*)(p->layers[layer].start); if ( h->th_offx2 & TH_RSV ) { diff --git a/src/network_inspectors/port_scan/ps_detect.cc b/src/network_inspectors/port_scan/ps_detect.cc index a59ed8a14..249f641ed 100644 --- a/src/network_inspectors/port_scan/ps_detect.cc +++ b/src/network_inspectors/port_scan/ps_detect.cc @@ -575,7 +575,7 @@ int PortScan::ps_get_proto(PS_PKT *ps_pkt, int *proto) || ((p->icmph != NULL) && (p->icmph->type == ICMP_DEST_UNREACH) && ((p->icmph->code == ICMP_PORT_UNREACH) || (p->icmph->code == ICMP_PKT_FILTERED)) - && (p->orig_tcph != NULL))) + && (p->proto_bits & PROTO_BIT__TCP_EMBED_ICMP))) { *proto = PS_PROTO_TCP; return 0; @@ -588,7 +588,7 @@ int PortScan::ps_get_proto(PS_PKT *ps_pkt, int *proto) || ((p->icmph != NULL) && (p->icmph->type == ICMP_DEST_UNREACH) && ((p->icmph->code == ICMP_PORT_UNREACH) || (p->icmph->code == ICMP_PKT_FILTERED)) - && (p->orig_udph != NULL))) + && (p->proto_bits & PROTO_BIT__UDP_EMBED_ICMP))) { *proto = PS_PROTO_UDP; return 0; diff --git a/src/protocols/CMakeLists.txt b/src/protocols/CMakeLists.txt index 22f1afc78..6b4229c2a 100644 --- a/src/protocols/CMakeLists.txt +++ b/src/protocols/CMakeLists.txt @@ -5,6 +5,8 @@ set (PROTOCOL_HEADERS eth.h icmp4.h icmp6.h + ip.cc + ip.h ipv4.h ipv6.h gre.h diff --git a/src/protocols/Makefile.am b/src/protocols/Makefile.am index 76180e5e2..9991874a9 100644 --- a/src/protocols/Makefile.am +++ b/src/protocols/Makefile.am @@ -10,6 +10,8 @@ eapol.h \ eth.h \ icmp4.h \ icmp6.h \ +ip.h \ +ip.cc \ ipv4.h \ ipv6.h \ gre.h \ diff --git a/src/protocols/icmp4.h b/src/protocols/icmp4.h index 171afcb90..0c48700b2 100644 --- a/src/protocols/icmp4.h +++ b/src/protocols/icmp4.h @@ -26,7 +26,7 @@ #include "main/snort_types.h" #include "protocols/ipv4.h" -namespace icmp4 +namespace icmp { namespace detail @@ -176,7 +176,7 @@ struct ICMPHdr /* IP header for unreach */ struct ih_ip { - ipv4::IPHdr *ip; + ip::IPHdr *ip; /* options and then 64 bits of data */ } ip; @@ -224,12 +224,12 @@ static inline uint8_t unreach_data() return detail::ICMP_UNREACH_DATA; } -} //namespace icmp4 +} //namespace icmp -typedef icmp4::ICMPbaseHdr ICMPbaseHdr; -typedef icmp4::ICMPHdr ICMPHdr; +typedef icmp::ICMPbaseHdr ICMPbaseHdr; +typedef icmp::ICMPHdr ICMPHdr; #ifndef ICMP_ECHOREPLY const uint8_t ICMP_ECHOREPLY = 0; /* Echo Reply */ diff --git a/src/protocols/ip.cc b/src/protocols/ip.cc new file mode 100644 index 000000000..74e69bea0 --- /dev/null +++ b/src/protocols/ip.cc @@ -0,0 +1,165 @@ +/* +** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. +** Copyright (C) 2007-2013 Sourcefire, Inc. +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License Version 2 as +** published by the Free Software Foundation. You may not use, modify or +** distribute this program under any other version of the GNU General +** Public License. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +// ip.cc author Josh Rosenbaum + +#include "protocols/ip.h" +#include "protocols/packet.h" + +namespace ip +{ + +void IpApi::reset() +{ + ip4h = nullptr; + ip6h = nullptr; + src_p = nullptr; + dst_p = nullptr; +} + +void IpApi::set(const IPHdr* h4) +{ + ip4h = h4; + ip6h = nullptr; + src_p = nullptr; + dst_p = nullptr; +} + +void IpApi::set(const ipv6::IP6RawHdr* h6) +{ + ip6h = h6; + ip4h = nullptr; + src_p = nullptr; + dst_p = nullptr; +} + +bool IpApi::set(const uint8_t* raw_ip_data) +{ + const IPHdr* h4 = reinterpret_cast(raw_ip_data); + if (h4->get_ver() == 4) + { + set(h4); + return true; + } + + const ipv6::IP6RawHdr* h6 = + reinterpret_cast(raw_ip_data); + + if (h6->get_ver() != 6) + return false; + + set(h6); + return true; +} + +const sfip_t* IpApi::get_src() +{ + if (src_p) + return src_p; + + if(ip4h) + { + src.family = AF_INET; + src.bits = 32; + + // TODO: Make this a pointer rather than copying + // will likely need to change Snort++ + src.ip32[0] = *(uint32_t*)(&ip4h->ip_src); + std::memset(&(src.ip32[1]), 0, 12); + } + else if (ip6h) + { + src.family = AF_INET6; + src.bits = 128; + + std::memcpy(&(src.ip8), &(ip6h->ip6_src), 16); + } + else + { + return nullptr; + } + + src_p = &src; + return src_p; +} + + +const sfip_t* IpApi::get_dst() +{ + if (dst_p) + return dst_p; + + if(ip4h) + { + dst.family = AF_INET; + dst.bits = 32; + + // TODO: Make this a pointer rather than copying + // will likely need to change Snort++ + dst.ip32[0] = *(uint32_t*)(&ip4h->ip_dst); + std::memset(&(dst.ip32[1]), 0, 12); + } + else if (ip6h) + { + dst.family = AF_INET6; + dst.bits = 128; + std::memcpy(&(dst.ip8), &(ip6h->ip6_dst), 16); + } + else + { + return nullptr; + } + + dst_p = &dst; + return dst_p; + +} + +uint32_t IpApi::id(const Packet* const p) +{ + if (ip4h) + return ip4h->get_id(); + + // ensure we have an ipv6 frag + if (p->ip6_extension_count == 0 || p->ip_frag_start == 0) + return 0; + + const IP6Frag* const frag_hdr = reinterpret_cast( + p->ip6_extensions[p->ip6_frag_index].data); + + return frag_hdr->get_id(); +} + +uint16_t IpApi::off(const Packet* const p) +{ + if (ip4h) + return ip4h->get_id(); + + // ensure we have an ipv6 frag + if (p->ip6_extension_count == 0 || p->ip_frag_start == 0) + return 0; + + const IP6Frag* const frag_hdr = reinterpret_cast( + p->ip6_extensions[p->ip6_frag_index].data); + + return frag_hdr->get_off(); +} + + +} // namespace protocols diff --git a/src/protocols/ip.h b/src/protocols/ip.h new file mode 100644 index 000000000..e032f0b3e --- /dev/null +++ b/src/protocols/ip.h @@ -0,0 +1,94 @@ +/* +** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License Version 2 as +** published by the Free Software Foundation. You may not use, modify or +** distribute this program under any other version of the GNU General +** Public License. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +// ip.h author Josh Rosenbaum + +#ifndef WIN32 +#include +#include +#include +#else /* !WIN32 */ +#include +#ifndef IFNAMSIZ +#define IFNAMESIZ MAX_ADAPTER_NAME +#endif /* !IFNAMSIZ */ +#endif /* !WIN32 */ + +#include + +#include "protocols/ipv4.h" +#include "protocols/ipv6.h" +#include "sfip/sfip_t.h" + +#ifndef IP_H +#define IP_H + +class Packet; + +namespace ip +{ + +// keeping this as a class to avoid confusion. +class IpApi +{ +public: +// IpApi(); constructor and destructor MUST remain a trivial. Adding +// ~IpApi(); any non-trivial code will cause a compilation failure. + + void set(const IPHdr* h4); + void set(const ipv6::IP6RawHdr* h6); + bool set(const uint8_t* raw_ip_data); + void reset(); + const sfip_t* get_src(); + const sfip_t* get_dst(); + uint32_t id(const Packet* const p); + uint16_t off(const Packet* const p); + + + inline uint16_t tos() + { return ip4h ? ip4h->get_tos() : ip6h ? ip6h->get_tos() : 0; } + + inline uint8_t ttl() + { return ip4h ? ip4h->get_ttl() : ip6h ? ip6h->get_hop_lim() : 0; } + + inline uint8_t proto() + { return ip4h ? ip4h->get_proto() : ip6h ? ip6h->get_next() : 0; } + + inline uint16_t len() + { return ip4h ? ip4h->get_len() : ip6h ? ip6h->get_len() : 0; } + + inline uint8_t hlen() + { return ip4h ? ip4h->get_hlen() : ip6h ? ip6h->get_hlen() : 0; } + + inline uint8_t ver() + { return ip4h ? ip4h->get_ver() : ip6h ? ip6h->get_ver() : 0; } + + +private: + sfip_t src; + sfip_t dst; + const sfip_t* src_p; + const sfip_t* dst_p; + const IPHdr* ip4h; + const ipv6::IP6RawHdr* ip6h; +}; + +} // namespace ip + +#endif diff --git a/src/protocols/ipv4.h b/src/protocols/ipv4.h index d015401c9..04474d205 100644 --- a/src/protocols/ipv4.h +++ b/src/protocols/ipv4.h @@ -19,9 +19,6 @@ */ -#ifndef IPV4_H -#define IPV4_H - #include @@ -39,6 +36,11 @@ #include "sfip/sfip_t.h" #include "protocols/protocol_ids.h" // include ipv4 protocol numbers + + +#ifndef IPV4_H +#define IPV4_H + #define ETHERNET_TYPE_IP 0x0800 #ifndef IP_MAXPACKET @@ -46,20 +48,21 @@ #endif /* IP_MAXPACKET */ -namespace ipv4 +namespace ip { namespace detail { /* ip option type codes */ -const uint32_t IP4_THIS_NET = 0x00; // msb -const uint32_t IP4_MULTICAST = 0x0E; // ms nibble -const uint32_t IP4_RESERVED = 0x0F; // ms nibble -const uint32_t IP4_LOOPBACK = 0x7F; // msb -const uint32_t IP4_BROADCAST = 0xffffffff; -const uint8_t IP_HEADER_LEN = 20; +constexpr uint32_t IP4_THIS_NET = 0x00; // msb +constexpr uint32_t IP4_MULTICAST = 0x0E; // ms nibble +constexpr uint32_t IP4_RESERVED = 0x0F; // ms nibble +constexpr uint32_t IP4_LOOPBACK = 0x7F; // msb +constexpr uint32_t IP4_BROADCAST = 0xffffffff; } // namespace detail +// not included in details since this should not be hidden +constexpr uint8_t IP4_HEADER_LEN = 20; enum class IPOptionCodes : std::uint8_t { @@ -83,6 +86,15 @@ struct IpOptions uint8_t code; uint8_t len; /* length of the data section */ const uint8_t *data; + + inline bool is_opt_rtralt() const + { return code == static_cast(IPOptionCodes::RTRALT); } + + inline bool is_opt_ts() const + { return code == static_cast(IPOptionCodes::TS); } + + inline bool is_opt_rr() const + { return code == static_cast(IPOptionCodes::RR); } }; // This must be a standard layour struct! @@ -96,8 +108,41 @@ struct IPHdr uint8_t ip_ttl; /* time to live field */ uint8_t ip_proto; /* datagram protocol */ uint16_t ip_csum; /* checksum */ - struct in_addr ip_src; /* source IP */ - struct in_addr ip_dst; /* dest IP */ + in_addr ip_src; /* source IP */ + in_addr ip_dst; /* dest IP */ + + inline uint8_t get_hlen() const + { return ip_verhl & 0x0f; } + + inline uint8_t get_ver() const + { return ((ip_verhl & 0xf0) >> 4); } + + inline uint8_t get_tos() const + { return ip_tos; }; + + inline uint16_t get_len() const + { return ip_len; } + + inline uint32_t get_id() const + { return (uint32_t)ip_id; } + + inline uint16_t get_off() const + { return ip_off; } + + inline uint8_t get_ttl() const + { return ip_ttl; } + + inline uint8_t get_proto() const + { return ip_proto; } + + inline uint16_t get_csum() const + { return ip_csum; } + + inline const in_addr* get_src() const + { return &ip_src; } + + inline const in_addr* get_dst() const + { return &ip_dst; } } ; @@ -138,17 +183,6 @@ static inline bool isPrivateIP(uint32_t addr) return false; } - -static inline uint16_t prot_id() -{ - return IPPROTO_ID_IPIP; -} - -static inline int ethertype_ip() -{ - return ETHERTYPE_IPV4; -} - static inline bool is_broadcast(uint32_t addr) { return (addr == detail::IP4_BROADCAST); @@ -159,51 +193,6 @@ static inline bool is_multicast(uint8_t addr) return (addr == detail::IP4_MULTICAST); } -static inline bool is_opt_rr(IPOptionCodes code) -{ - return (code == IPOptionCodes::RR); -} - -static inline bool is_opt_rr(uint8_t code) -{ - return (static_cast(code) == IPOptionCodes::RR); -} - -static inline bool is_opt_rtralt(IPOptionCodes code) -{ - return (code == IPOptionCodes::RTRALT); -} - -static inline bool is_opt_rtralt(uint8_t code) -{ - return (static_cast(code) == IPOptionCodes::RTRALT); -} - -static inline bool is_opt_ts(IPOptionCodes code) -{ - return (code == IPOptionCodes::TS); -} - -static inline bool is_opt_ts(uint8_t code) -{ - return (static_cast(code) == IPOptionCodes::TS); -} - -static inline bool is_ethertype_ip(int proto) -{ - return (proto == ETHERTYPE_IPV4); -} - -static inline bool is_ipv4(IPHdr* p) -{ - return (p->ip_verhl >> 4) == 4; -} - -static inline bool is_ipv4(const IP4Hdr* p) -{ - return (p->ip_verhl >> 4) == 4; -} - static inline bool is_ipv4(uint8_t ch) { return (ch >> 4) == 4; @@ -229,11 +218,6 @@ static inline uint8_t get_version(IP4Hdr* p) return (p->ip_verhl & 0xf0) >> 4; } -static inline uint8_t hdr_len() -{ - return detail::IP_HEADER_LEN; -} - static inline bool is_loopback(uint8_t addr) { return addr == detail::IP4_LOOPBACK; @@ -269,31 +253,31 @@ static inline void set_hlen(IP4Hdr* p, uint8_t value) p->ip_verhl = (unsigned char)(((p)->ip_verhl & 0xf0) | (value & 0x0f)); } -} /* namespace ipv4 */ +} /* namespace ip */ /* tcpdump shows us the way to cross platform compatibility */ /* we need to change them as well as get them */ // TYPEDEF WHICH NEED TO BE DELETED -typedef ipv4::IPHdr IPHdr; -typedef ipv4::IP4Hdr IP4Hdr; +typedef ip::IPHdr IPHdr; +typedef ip::IP4Hdr IP4Hdr; -const uint8_t IPOPT_EOL = 0x00; -const uint8_t IPOPT_NOP = 0x01; -const uint8_t IPOPT_RR = 0x07; -const uint8_t IPOPT_TS = 0x44; -const uint8_t IPOPT_SECURITY = 0x82; -const uint8_t IPOPT_LSRR = 0x83; -const uint8_t IPOPT_LSRR_E = 0x84; -const uint8_t IPOPT_ESEC = 0x85; -const uint8_t IPOPT_SATID = 0x88; -const uint8_t IPOPT_SSRR = 0x89; -const uint8_t IPOPT_RTRALT = 0x94; -const uint8_t IPOPT_ANY = 0xff; +constexpr uint8_t IPOPT_EOL = 0x00; +constexpr uint8_t IPOPT_NOP = 0x01; +constexpr uint8_t IPOPT_RR = 0x07; +constexpr uint8_t IPOPT_TS = 0x44; +constexpr uint8_t IPOPT_SECURITY = 0x82; +constexpr uint8_t IPOPT_LSRR = 0x83; +constexpr uint8_t IPOPT_LSRR_E = 0x84; +constexpr uint8_t IPOPT_ESEC = 0x85; +constexpr uint8_t IPOPT_SATID = 0x88; +constexpr uint8_t IPOPT_SSRR = 0x89; +constexpr uint8_t IPOPT_RTRALT = 0x94; +constexpr uint8_t IPOPT_ANY = 0xff; -#define IP_HEADER_LEN ipv4::hdr_len() +/* #define IP_HEADER_LEN ip::ip4_hdr_len() */ #endif diff --git a/src/protocols/ipv6.h b/src/protocols/ipv6.h index ff2ea5e76..d43183694 100644 --- a/src/protocols/ipv6.h +++ b/src/protocols/ipv6.h @@ -43,11 +43,9 @@ namespace ipv6 namespace detail { -const uint16_t ETHERNET_TYPE_IPV6 = 0x86dd; -const uint16_t IPV6_PROT_ID = 41; -const uint8_t IP6_HEADER_LEN = 40; -const uint8_t IP6_MULTICAST = 0xFF; // first/most significant octet -const uint32_t MIN_EXT_LEN = 8; +constexpr uint8_t IP6_HEADER_LEN = 40; +constexpr uint8_t IP6_MULTICAST = 0xFF; // first/most significant octet +constexpr uint32_t MIN_EXT_LEN = 8; } // namespace @@ -108,7 +106,13 @@ struct IP6Frag uint8_t ip6f_reserved; /* reserved field */ uint16_t ip6f_offlg; /* offset, reserved, and flag */ uint32_t ip6f_ident; /* identification */ -} ; + + inline uint32_t get_id() const + { return ip6f_ident; } + + inline uint16_t get_off() const + { return ip6f_offlg; } +}; struct IP6RawHdr @@ -119,10 +123,40 @@ struct IP6RawHdr uint8_t ip6_next; /* next header */ uint8_t ip6_hoplim; /* hop limit */ - struct in6_addr ip6_src; /* source address */ - struct in6_addr ip6_dst; /* destination address */ + in6_addr ip6_src; /* source address */ + in6_addr ip6_dst; /* destination address */ + + inline const in6_addr* get_src() const + { return &ip6_src; } + + inline const in6_addr* get_dst() const + { return &ip6_dst; } + + inline uint16_t get_tos() const + { return (uint16_t)((ntohl(ip6_vtf) & 0x0FF00000) >> 20); } + + inline uint8_t get_hop_lim() const + { return ip6_hoplim; } + + inline uint16_t get_len() const + { return ip6_payload_len; } + + inline uint8_t get_next() const + { return ip6_next; } + + inline uint8_t get_ver() const + { return (uint8_t)(ntohl(ip6_vtf) >> 28); } + + inline uint8_t get_hdr_len() const + { return (uint8_t) detail::IP6_HEADER_LEN; } + + // becaise Snort expects this in terms of 32 bit words. + inline uint8_t get_hlen() const + { return detail::IP6_HEADER_LEN / 4; } + }; + struct IP6Hdr { uint32_t vcl; /* version, class, and label */ @@ -166,16 +200,6 @@ inline uint8_t hdr_len() return detail::IP6_HEADER_LEN; } -inline uint16_t ethertype() -{ - return detail::ETHERNET_TYPE_IPV6; -} - -inline uint16_t prot_id() -{ - return detail::IPV6_PROT_ID; -} - inline bool is_multicast(uint8_t addr) { return addr == detail::IP6_MULTICAST; diff --git a/src/protocols/layer.cc b/src/protocols/layer.cc index fd7ff9206..973657b0d 100644 --- a/src/protocols/layer.cc +++ b/src/protocols/layer.cc @@ -21,17 +21,19 @@ #include "protocols/packet.h" +#include "protocols/layer.h" #include "protocols/ipv4.h" #include "protocols/ipv6.h" +#include "protocols/ip.h" namespace layer { -static inline const uint8_t *find_layer(const Layer *lyr, +static inline const uint8_t* find_outer_layer(const Layer* lyr, uint8_t num_layers, uint16_t prot_id) { - for(int i = num_layers - 1; i >= 0 ; i--) + for(int i = 0; i < num_layers ; i++) { if (lyr->prot_id == prot_id) return lyr->start; @@ -40,28 +42,55 @@ static inline const uint8_t *find_layer(const Layer *lyr, return nullptr; } -static inline const uint8_t *find_layer(const Layer *lyr, +static inline const uint8_t* find_inner_layer(const Layer* lyr, + uint8_t num_layers, + uint16_t prot_id) +{ + int tmp = num_layers-1; + lyr = &lyr[tmp]; + + for(int i = tmp; i >= 0 ; i--) + { + if (lyr->prot_id == prot_id) + return lyr->start; + lyr--; + } + return nullptr; +} + +static inline const uint8_t* find_inner_layer(const Layer* lyr, uint8_t num_layers, uint16_t prot_id1, uint16_t prot_id2) { + int tmp = num_layers-1; + lyr = &lyr[tmp]; + for(int i = num_layers - 1; i >= 0; i--) { if (lyr->prot_id == prot_id1 || lyr->prot_id == prot_id2) return lyr->start; - lyr++; + lyr--; } return nullptr; } + +const uint8_t* get_inner_layer(const Packet* p, uint16_t proto) +{ return find_inner_layer(p->layers, p->num_layers, proto); } + +const uint8_t* get_outer_layer(const Packet* p, uint16_t proto) +{ return find_outer_layer(p->layers, p->num_layers, proto); } + + const arp::EtherARP* get_arp_layer(const Packet* const p) { uint8_t num_layers = p->num_layers; const Layer *lyr = p->layers; return reinterpret_cast( - find_layer(lyr, num_layers, ETHERTYPE_ARP, ETHERTYPE_REVARP)); + find_inner_layer(lyr, num_layers, ETHERTYPE_ARP, ETHERTYPE_REVARP)); } const gre::GREHdr* get_gre_layer(const Packet* const p) @@ -70,7 +99,7 @@ const gre::GREHdr* get_gre_layer(const Packet* const p) const Layer *lyr = p->layers; return reinterpret_cast( - find_layer(lyr, num_layers, IPPROTO_ID_GRE)); + find_inner_layer(lyr, num_layers, IPPROTO_ID_GRE)); } const eapol::EtherEapol* get_eapol_layer(const Packet* const p) @@ -79,7 +108,7 @@ const eapol::EtherEapol* get_eapol_layer(const Packet* const p) const Layer *lyr = p->layers; return reinterpret_cast( - find_layer(lyr, num_layers, ETHERTYPE_EAPOL)); + find_inner_layer(lyr, num_layers, ETHERTYPE_EAPOL)); } const vlan::VlanTagHdr* get_vlan_layer(const Packet* const p) @@ -88,7 +117,7 @@ const vlan::VlanTagHdr* get_vlan_layer(const Packet* const p) const Layer *lyr = p->layers; return reinterpret_cast( - find_layer(lyr, num_layers, ETHERTYPE_8021Q)); + find_inner_layer(lyr, num_layers, ETHERTYPE_8021Q)); } const eth::EtherHdr* get_eth_layer(const Packet* const p) @@ -98,7 +127,7 @@ const eth::EtherHdr* get_eth_layer(const Packet* const p) // First, search for the inner eth layer (transbridging) const eth::EtherHdr* eh = reinterpret_cast( - find_layer(lyr, num_layers, ETHERTYPE_TRANS_ETHER_BRIDGING)); + find_inner_layer(lyr, num_layers, ETHERTYPE_TRANS_ETHER_BRIDGING)); // if no inner eth layer, assume root layer is eth (callers job to confirm) return eh ? eh : reinterpret_cast(get_root_layer(p)); @@ -155,4 +184,62 @@ int get_inner_ip_lyr(const Packet* const p) return -1; } +bool set_api_ip_embed_icmp(Packet* const p) +{ return set_api_ip_embed_icmp(p, p->ip_api); } + +bool set_api_ip_embed_icmp(const Packet* p, ip::IpApi& api) +{ + int num_layers = p->num_layers - 1; + const Layer* lyr = &p->layers[num_layers]; + + for(int i = num_layers; i >= 0; i--) + { + if (lyr->prot_id == IP_EMBEDDED_IN_ICMP4) + { + const ip::IPHdr* ip4h = + reinterpret_cast(lyr->start); + api.set(ip4h); + return true; + } + else if (lyr->prot_id == IP_EMBEDDED_IN_ICMP6) + { + const ipv6::IP6RawHdr* ip6h = + reinterpret_cast(lyr->start); + api.set(ip6h); + return true; + } + + lyr--; + } + + api.reset(); + return false; +} + +const uint8_t* get_prot_embed_icmp(const Packet* const p) +{ + return find_inner_layer(p->layers, + p->num_layers, + PROT_EMBEDDED_IN_ICMP); +} + +const tcp::TCPHdr* get_tcp_embed_icmp(const Packet* const p) +{ + return reinterpret_cast( + get_prot_embed_icmp(p)); +} + +const udp::UDPHdr* get_udp_embed_icmp(const Packet* const p) +{ + return reinterpret_cast( + get_prot_embed_icmp(p)); +} + +const icmp::ICMPHdr* get_icmp_embed_icmp(const Packet* const p) +{ + return reinterpret_cast( + get_prot_embed_icmp(p)); +} + + } // namespace layer diff --git a/src/protocols/layer.h b/src/protocols/layer.h index e76a0b6ef..120c5b00f 100644 --- a/src/protocols/layer.h +++ b/src/protocols/layer.h @@ -26,7 +26,6 @@ #include "codecs/sf_protocols.h" - struct Layer { uint16_t prot_id; PROTO_ID proto; @@ -63,12 +62,33 @@ namespace eth struct EtherHdr; } +namespace ip +{ +class IpApi; +} + +namespace tcp +{ +struct TCPHdr; +} + +namespace udp +{ +struct UDPHdr; +} + +namespace icmp +{ +struct ICMPHdr; +} namespace layer { // all of these functions will begin search from layer 0, // and will return the first function they find. +const uint8_t* get_inner_layer(const Packet*, uint16_t proto); +const uint8_t* get_outer_layer(const Packet*, uint16_t proto); const arp::EtherARP* get_arp_layer(const Packet*); @@ -78,6 +98,27 @@ const eapol::EtherEapol* get_eapol_layer(const Packet*); const eth::EtherHdr* get_eth_layer(const Packet*); const uint8_t* get_root_layer(const Packet* const); + +// ICMP with Embedded IP layer + + +// Sets the Packet's api to be the IP layer which is +// embedded inside an ICMP layer. +// RETURN: +// true - ip layer found and api set +// false - ip layer NOT found, api reset +bool set_api_ip_embed_icmp(const Packet*); +bool set_api_ip_embed_icmp(const Packet*, ip::IpApi& api); + +// When a protocol is embedded in ICMP, this function +// will return a pointer to the layer. Use the +// proto_bits to determine what this layer is! +const uint8_t* get_prot_embed_icmp(const Packet* const); +const tcp::TCPHdr* get_tcp_embed_icmp(const Packet* const); +const udp::UDPHdr* get_udp_embed_icmp(const Packet* const); +const icmp::ICMPHdr* get_icmp_embed_icmp(const Packet* const); + + int get_inner_ip_lyr(const Packet* const p); uint16_t get_outer_ip_next_proto(const Packet* const); diff --git a/src/protocols/packet.h b/src/protocols/packet.h index 18658da00..9b61517dd 100644 --- a/src/protocols/packet.h +++ b/src/protocols/packet.h @@ -62,6 +62,7 @@ extern "C" { #include "protocols/icmp4.h" #include "protocols/icmp6.h" #include "protocols/mpls.h" +#include "protocols/ip.h" /* D E F I N E S ************************************************************/ @@ -147,15 +148,15 @@ enum PseudoPacketType{ #define DEFAULT_MPLS_PAYLOADTYPE MPLS_PAYLOADTYPE_IPV4 #define DEFAULT_LABELCHAIN_LENGTH -1 -const int32_t MAX_PORTS = 65536; -const uint16_t NUM_IP_PROTOS = 256; -const int16_t SFTARGET_UNKNOWN_PROTOCOL = -1; -const uint8_t IP_OPTMAX = 40; -const uint8_t TCP_OPTLENMAX = 40; /* (((2^4) - 1) * 4 - TCP_HEADER_LEN) */ -const uint8_t IP6_EXTMAX = 8; -const uint8_t MIN_TTL = 64; -const uint8_t MAX_TTL = 255; -const uint8_t LAYER_MAX = 32; +constexpr int32_t MAX_PORTS = 65536; +constexpr uint16_t NUM_IP_PROTOS = 256; +constexpr int16_t SFTARGET_UNKNOWN_PROTOCOL = -1; +constexpr uint8_t IP_OPTMAX = 40; +constexpr uint8_t TCP_OPTLENMAX = 40; /* (((2^4) - 1) * 4 - TCP_HEADER_LEN) */ +constexpr uint8_t IP6_EXTMAX = 8; +constexpr uint8_t MIN_TTL = 64; +constexpr uint8_t MAX_TTL = 255; +constexpr uint8_t LAYER_MAX = 32; @@ -181,13 +182,13 @@ struct Packet //vvv----------------------------- - const IPHdr *iph, *orig_iph;/* and orig. headers for ICMP_*_UNREACH family */ + const IPHdr *iph; const IPHdr *inner_iph; /* if IP-in-IP, this will be the inner IP header */ const IPHdr *outer_iph; /* if IP-in-IP, this will be the outer IP header */ - const TCPHdr *tcph, *orig_tcph; - const udp::UDPHdr *udph, *orig_udph; + const tcp::TCPHdr *tcph; + const udp::UDPHdr *udph; const udp::UDPHdr *outer_udph; /* if Teredo + UDP, this will be the outer UDP header */ - const ICMPHdr *icmph, *orig_icmph; + const ICMPHdr *icmph; const uint8_t *data; /* packet payload pointer */ const uint8_t *ip_data; /* IP payload pointer */ @@ -197,16 +198,13 @@ struct Packet Flow* flow; /* for session tracking */ //vvv----------------------------- - ipv4::IP4Hdr *ip4h; + ip::IP4Hdr *ip4h; ipv6::IP6Hdr *ip6h; - icmp6::ICMP6Hdr *icmp6h; IPH_API* iph_api; - IPH_API* orig_iph_api; IPH_API* outer_iph_api; int family; - int orig_family; int outer_family; //^^^----------------------------- @@ -231,8 +229,6 @@ struct Packet //vvv----------------------------- uint16_t sp; /* source port (TCP/UDP) */ uint16_t dp; /* dest port (TCP/UDP) */ - uint16_t orig_sp; /* source port (TCP/UDP) of original datagram */ - uint16_t orig_dp; /* dest port (TCP/UDP) of original datagram */ //^^^----------------------------- // and so on ... @@ -252,7 +248,7 @@ struct Packet const DAQ_PktHdr_t *pkth; // packet meta data const uint8_t *pkt; // raw packet data - ipv4::IpOptions ip_options[IP_OPTMAX]; /* ip options decode structure */ + ip::IpOptions ip_options[IP_OPTMAX]; /* ip options decode structure */ Options tcp_options[TCP_OPTLENMAX]; /* tcp options decode struct */ IP6Option ip6_extensions[IP6_EXTMAX]; /* IPv6 Extension References */ @@ -265,10 +261,11 @@ struct Packet const ipv6::IP6RawHdr* raw_ip6h; // innermost raw ip6 header Layer layers[LAYER_MAX]; /* decoded encapsulations */ - ipv4::IP4Hdr inner_ip4h; + ip::IP4Hdr inner_ip4h; ipv6::IP6Hdr inner_ip6h; - ipv4::IP4Hdr outer_ip4h; + ip::IP4Hdr outer_ip4h; ipv6::IP6Hdr outer_ip6h; + ip::IpApi ip_api; MplsHdr mplsHdr; @@ -300,7 +297,10 @@ struct Packet #define PROTO_BIT__MPLS 0x0080 #define PROTO_BIT__VLAN 0x0100 #define PROTO_BIT__ETH 0x0200 -#define PROTO_BIT__FREE 0x7c00 +#define PROTO_BIT__TCP_EMBED_ICMP 0x0400 +#define PROTO_BIT__UDP_EMBED_ICMP 0x0800 +#define PROTO_BIT__ICMP_EMBED_ICMP 0x1000 +#define PROTO_BIT__FREE 0x6000 #define PROTO_BIT__OTHER 0x8000 #define PROTO_BIT__ALL 0xffff @@ -309,9 +309,9 @@ struct Packet #define DECODE__MF 0x02 /* more fragments flag */ #define DECODE__DF 0x04 /* don't fragment flag */ #define DECODE__RF 0x08 /* IP reserved bit */ -#define DECODE__ESP 0x10 /* flag to indicate an ESP layer has been seen */ -#define DECODE__UNSURE_ENCAP 0x20 /* packet may have incorrect encapsulation layer. */ - /* don't alert if "next layer" is invalid. */ +#define DECODE__TRUST_ON_FAIL 0x10 /* if decode fails, set the PKT_TRUST flag */ +#define DECODE__UNSURE_ENCAP 0x20 /* packet may have incorrect encapsulation layer. */ + /* don't alert if "next layer" is invalid. */ #define DECODE__FREE 0xC0 #define IsIP(p) (IPH_IS_VALID(p)) diff --git a/src/protocols/protocol_ids.h b/src/protocols/protocol_ids.h index 03dce3d0e..da795f386 100644 --- a/src/protocols/protocol_ids.h +++ b/src/protocols/protocol_ids.h @@ -47,27 +47,30 @@ * http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml */ -const uint16_t IPPROTO_ID_HOPOPTS = 0; -const uint16_t IPPROTO_ID_ICMPV4 = 1; -const uint16_t IPPROTO_ID_IPIP = 4; -const uint16_t IPPROTO_ID_IPV6 = 41; -const uint16_t IPPROTO_ID_ROUTING = 43; -const uint16_t IPPROTO_ID_FRAGMENT = 44; -const uint16_t IPPROTO_ID_GRE = 47; -const uint16_t IPPROTO_ID_ESP = 50; -const uint16_t IPPROTO_ID_AH = 51; // RFC 4302 -const uint16_t IPPROTO_ID_ICMPV6 = 58; -const uint16_t IPPROTO_ID_NONEXT = 59; -const uint16_t IPPROTO_ID_DSTOPTS = 60; +constexpr uint16_t IPPROTO_ID_HOPOPTS = 0; +constexpr uint16_t IPPROTO_ID_ICMPV4 = 1; +constexpr uint16_t IPPROTO_ID_IPIP = 4; +constexpr uint16_t IPPROTO_ID_IPV6 = 41; +constexpr uint16_t IPPROTO_ID_ROUTING = 43; +constexpr uint16_t IPPROTO_ID_FRAGMENT = 44; +constexpr uint16_t IPPROTO_ID_GRE = 47; +constexpr uint16_t IPPROTO_ID_ESP = 50; +constexpr uint16_t IPPROTO_ID_AH = 51; // RFC 4302 +constexpr uint16_t IPPROTO_ID_ICMPV6 = 58; +constexpr uint16_t IPPROTO_ID_NONEXT = 59; +constexpr uint16_t IPPROTO_ID_DSTOPTS = 60; /* * Undefined Protocol! */ -const uint16_t FINISHED_DECODE = 0x0100; // Indicates Codecs have succesfully decoded packet -const uint16_t PROTOCOL_TEREDO = 0x0101; -const uint16_t PROTOCOL_GTP = 0x0102; +constexpr uint16_t FINISHED_DECODE = 0x0100; // Indicates Codecs have succesfully decoded packet +constexpr uint16_t PROTOCOL_TEREDO = 0x0101; +constexpr uint16_t PROTOCOL_GTP = 0x0102; +constexpr uint16_t IP_EMBEDDED_IN_ICMP4 = 0x0103; +constexpr uint16_t IP_EMBEDDED_IN_ICMP6 = 0x0104; +constexpr uint16_t PROT_EMBEDDED_IN_ICMP = 0x0105; @@ -81,17 +84,15 @@ const uint16_t PROTOCOL_GTP = 0x0102; */ -const uint16_t ETHERTYPE_TRANS_ETHER_BRIDGING = 0x6558; -const uint16_t ETHERTYPE_IPV4 = 0x0800; -const uint16_t ETHERTYPE_REVARP = 0x8035; -const uint16_t ETHERTYPE_ARP = 0x0806; -const uint16_t ETHERTYPE_8021Q = 0x8100; -const uint16_t ETHERTYPE_IPX = 0x8137; -const uint16_t ETHERTYPE_IPV6 = 0x86dd; -const uint16_t ETHERTYPE_PPP = 0x880B; -const uint16_t ETHERTYPE_EAPOL = 0x888e; +constexpr uint16_t ETHERTYPE_TRANS_ETHER_BRIDGING = 0x6558; +constexpr uint16_t ETHERTYPE_IPV4 = 0x0800; +constexpr uint16_t ETHERTYPE_REVARP = 0x8035; +constexpr uint16_t ETHERTYPE_ARP = 0x0806; +constexpr uint16_t ETHERTYPE_8021Q = 0x8100; +constexpr uint16_t ETHERTYPE_IPX = 0x8137; +constexpr uint16_t ETHERTYPE_IPV6 = 0x86dd; +constexpr uint16_t ETHERTYPE_PPP = 0x880B; +constexpr uint16_t ETHERTYPE_EAPOL = 0x888e; #endif - - diff --git a/src/protocols/tcp.h b/src/protocols/tcp.h index 300b85a82..48a5e845a 100644 --- a/src/protocols/tcp.h +++ b/src/protocols/tcp.h @@ -79,7 +79,7 @@ namespace tcp namespace detail { -const uint8_t TCP_HEADER_LEN = 20; +constexpr uint8_t TCP_HEADER_LEN = 20; } // namespace detail @@ -261,7 +261,5 @@ inline void set_tcp_x2(TCPHdr* tcph, uint8_t value) #define TCP_HEADER_LEN tcp::hdr_len() -#define TCPHdr tcp::TCPHdr - #endif /* TCP_H */ diff --git a/src/sfip/ipv6_port.h b/src/sfip/ipv6_port.h index 85f67cb62..a9d78b971 100644 --- a/src/sfip/ipv6_port.h +++ b/src/sfip/ipv6_port.h @@ -42,9 +42,6 @@ typedef sfip_t *snort_ip_p; #define GET_SRC_IP(p) ((p)->iph_api->iph_ret_src(p)) #define GET_DST_IP(p) ((p)->iph_api->iph_ret_dst(p)) -#define GET_ORIG_SRC(p) ((p)->orig_iph_api->orig_iph_ret_src(p)) -#define GET_ORIG_DST(p) ((p)->orig_iph_api->orig_iph_ret_dst(p)) - /* These are here for backwards compatibility */ #define GET_SRC_ADDR(x) GET_SRC_IP(x) #define GET_DST_ADDR(x) GET_DST_IP(x) @@ -68,12 +65,19 @@ typedef sfip_t *snort_ip_p; #define GET_IPH_VER(p) (p)->iph_api->iph_ret_ver(p) #define GET_IPH_PROTO(p) ((uint8_t)(IS_IP6(p) ? ((p)->ip6h->next) : ((p)->iph_api->iph_ret_proto(p)))) + +#if 0 + +#define GET_ORIG_SRC(p) ((p)->orig_iph_api->orig_iph_ret_src(p)) +#define GET_ORIG_DST(p) ((p)->orig_iph_api->orig_iph_ret_dst(p)) #define GET_ORIG_IPH_PROTO(p) (p)->orig_iph_api->orig_iph_ret_proto(p) #define GET_ORIG_IPH_VER(p) (p)->orig_iph_api->orig_iph_ret_ver(p) #define GET_ORIG_IPH_LEN(p) (p)->orig_iph_api->orig_iph_ret_len(p) #define GET_ORIG_IPH_OFF(p) (p)->orig_iph_api->orig_iph_ret_off(p) #define GET_ORIG_IPH_PROTO(p) (p)->orig_iph_api->orig_iph_ret_proto(p) +#endif + /* XXX make sure these aren't getting confused with sfip_is_valid within the code */ #define IPH_IS_VALID(p) iph_is_valid(p) diff --git a/src/sfip/sf_iph.cc b/src/sfip/sf_iph.cc index 2591bdb53..1ed500092 100644 --- a/src/sfip/sf_iph.cc +++ b/src/sfip/sf_iph.cc @@ -308,10 +308,12 @@ uint8_t ip4_ret_ver(const Packet *p) return (p->iph->ip_verhl & 0xf0) >> 4; } +#if 0 uint8_t orig_ip4_ret_ver(const Packet *p) { return (p->orig_iph->ip_verhl & 0xf0) >> 4; } +#endif uint8_t ip4_ret_hlen(const Packet *p) { @@ -320,7 +322,8 @@ uint8_t ip4_ret_hlen(const Packet *p) uint8_t orig_ip4_ret_hlen(const Packet *p) { - return p->orig_iph->ip_verhl & 0x0f; + return 0; +// return p->orig_iph->ip_verhl & 0x0f; } uint8_t ip6_ret_hlen(const Packet*) @@ -346,7 +349,7 @@ IPH_API ip4 = ip4_ret_off, ip4_ret_ver, ip4_ret_hlen, - +#if 0 orig_ip4_ret_src, orig_ip4_ret_dst, orig_ip4_ret_tos, @@ -357,7 +360,7 @@ IPH_API ip4 = orig_ip4_ret_off, orig_ip4_ret_ver, orig_ip4_ret_hlen, - +#endif IPH_API_V4 }; @@ -373,7 +376,7 @@ IPH_API ip6 = ip6_ret_off, ip6_ret_ver, ip6_ret_hlen, - +#if 0 orig_ip6_ret_src, orig_ip6_ret_dst, orig_ip6_ret_toc, @@ -384,7 +387,7 @@ IPH_API ip6 = orig_ip6_ret_off, orig_ip6_ret_ver, orig_ip6_ret_hlen, - +#endif IPH_API_V6 }; @@ -399,15 +402,6 @@ static inline void _set_callbacks(Packet* p, int family, char orig) p->family = family; } - else - { - if(family == AF_INET) - p->orig_iph_api = &ip4; - else - p->orig_iph_api = &ip6; - - p->orig_family = family; - } } void set_callbacks(Packet* p, int family, char orig) diff --git a/src/sfip/sf_iph.h b/src/sfip/sf_iph.h index 23e3f191a..62bfa3653 100644 --- a/src/sfip/sf_iph.h +++ b/src/sfip/sf_iph.h @@ -39,6 +39,7 @@ typedef struct _IPH_API uint8_t (*iph_ret_ver)(const Packet*); uint8_t (*iph_ret_hlen)(const Packet*); +#if 0 sfip_t * (*orig_iph_ret_src)(const Packet*); sfip_t * (*orig_iph_ret_dst)(const Packet*); uint16_t (*orig_iph_ret_tos)(const Packet*); @@ -49,7 +50,7 @@ typedef struct _IPH_API uint16_t (*orig_iph_ret_off)(const Packet*); uint8_t (*orig_iph_ret_ver)(const Packet*); uint8_t (*orig_iph_ret_hlen)(const Packet*); - +#endif char ver; } IPH_API; @@ -63,7 +64,6 @@ extern IPH_API ip6; #define NO_IP 0 void sfiph_build(Packet*, const void *hdr, int family); -void sfiph_orig_build(Packet*, const void *hdr, int family); /* Sets the callbacks to point at the family selected by * * "family". "family" is either AF_INET or AF_INET6 */ diff --git a/src/stream/icmp/icmp_session.cc b/src/stream/icmp/icmp_session.cc index c36177ee3..8017150f0 100644 --- a/src/stream/icmp/icmp_session.cc +++ b/src/stream/icmp/icmp_session.cc @@ -42,6 +42,7 @@ #include "profiler.h" #include "protocols/layer.h" #include "protocols/vlan.h" +#include "protocols/ip.h" THREAD_LOCAL SessionStats icmpStats; THREAD_LOCAL ProfileStats icmp_perf_stats; @@ -74,26 +75,45 @@ static int ProcessIcmpUnreach(Packet *p) { /* Handle ICMP unreachable */ FlowKey skey; - Flow *ssn = NULL; + Flow* ssn = NULL; uint16_t sport; uint16_t dport; - sfip_t *src; - sfip_t *dst; + const sfip_t* src; + const sfip_t* dst; + ip::IpApi iph; - /* No "orig" IP Header */ - if (!p->orig_iph) + /* Set the Ip API to the embedded IP Header. */ + if (!layer::set_api_ip_embed_icmp(p, iph)) return 0; - /* Get TCP/UDP/ICMP session from original protocol/port info - * embedded in the ICMP Unreach message. This is already decoded - * in p->orig_foo. TCP/UDP ports are decoded as p->orig_sp/dp. + /* Get IP/TCP/UDP/ICMP session from original protocol/port info + * embedded in the ICMP Unreach message. */ - skey.protocol = GET_ORIG_IPH_PROTO(p); - sport = p->orig_sp; - dport = p->orig_dp; + skey.protocol = iph.proto(); + src = iph.get_src(); + dst = iph.get_dst(); + + + if (p->proto_bits & PROTO_BIT__TCP_EMBED_ICMP) + { + const tcp::TCPHdr* tcph = layer::get_tcp_embed_icmp(p); + sport = ntohs(tcph->th_sport); + dport = ntohs(tcph->th_dport); + } + else if (p->proto_bits & PROTO_BIT__UDP_EMBED_ICMP) + { + const udp::UDPHdr* udph = layer::get_udp_embed_icmp(p); + + sport = ntohs(udph->uh_sport); + dport = ntohs(udph->uh_dport); + } + else + { + sport = 0; + dport = 0; + } + - src = GET_ORIG_SRC(p); - dst = GET_ORIG_DST(p); if (sfip_fast_lt6(src, dst)) { @@ -102,7 +122,7 @@ static int ProcessIcmpUnreach(Packet *p) COPY4(skey.ip_h, dst->ip32); skey.port_h = dport; } - else if (IP_EQUALITY(GET_ORIG_SRC(p), GET_ORIG_DST(p))) + else if (IP_EQUALITY(iph.get_src(), iph.get_dst())) { COPY4(skey.ip_l, src->ip32); COPY4(skey.ip_h, skey.ip_l); diff --git a/src/stream/ip/ip_defrag.cc b/src/stream/ip/ip_defrag.cc index b71e5a4b7..0ecea051b 100644 --- a/src/stream/ip/ip_defrag.cc +++ b/src/stream/ip/ip_defrag.cc @@ -916,7 +916,7 @@ static void FragRebuild(FragTracker *ft, Packet *p) DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Adjusting IP Header to %d bytes\n", new_ip_hlen);); - ipv4::set_hlen((IPHdr *)dpkt->iph, new_ip_hlen>>2); + ip::set_hlen((IPHdr *)dpkt->iph, new_ip_hlen>>2); ret = SafeMemcpy(rebuild_ptr, ft->ip_options_data, ft->ip_options_len, rebuild_ptr, rebuild_end); diff --git a/src/stream/tcp/tcp_session.cc b/src/stream/tcp/tcp_session.cc index 70cf2e631..9d6ce6022 100644 --- a/src/stream/tcp/tcp_session.cc +++ b/src/stream/tcp/tcp_session.cc @@ -85,6 +85,8 @@ #include "tcp_module.h" #include "stream/stream_splitter.h" +using namespace tcp; + THREAD_LOCAL ProfileStats s5TcpPerfStats; THREAD_LOCAL ProfileStats s5TcpNewSessPerfStats; THREAD_LOCAL ProfileStats s5TcpStatePerfStats;