From: Mike Stepanek (mstepane) Date: Fri, 3 Apr 2020 16:23:13 +0000 (+0000) Subject: Merge pull request #2077 in SNORT/snort3 from ~DERAMADA/snort3:gre_encode to master X-Git-Tag: 3.0.1-2~41 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2f85742173219b0af587095b4682fa2ab175446e;p=thirdparty%2Fsnort3.git Merge pull request #2077 in SNORT/snort3 from ~DERAMADA/snort3:gre_encode to master Squashed commit of the following: commit 14d1ebcee5a9b038c75e7c7ef2b5889dbe1e512f Author: deramada Date: Thu Mar 12 16:50:17 2020 -0400 codecs: Update GRE flags and offset for injected packets commit 2c99419277fa13e61819e54db9848c5fa523bf34 Author: Katura Harvey Date: Thu Feb 20 13:24:39 2020 -0500 codecs: GRE checksum updated for injected and rewritten packets --- diff --git a/src/codecs/ip/cd_gre.cc b/src/codecs/ip/cd_gre.cc index 8f4abc857..d25e3a02c 100644 --- a/src/codecs/ip/cd_gre.cc +++ b/src/codecs/ip/cd_gre.cc @@ -29,6 +29,8 @@ #include "main/snort_config.h" #include "protocols/gre.h" +#include "checksum.h" + #ifdef UNIT_TEST #include "catch/snort_catch.h" #endif @@ -70,6 +72,8 @@ public: void log(TextLog* const, const uint8_t* pkt, const uint16_t len) override; bool encode(const uint8_t* const raw_in, const uint16_t raw_len, EncState&, Buffer&, Flow*) override; + void update(const ip::IpApi& api, const EncodeFlags flags, uint8_t* raw_pkt, + uint16_t lyr_len, uint32_t& updated_len) override; }; static const uint32_t GRE_HEADER_LEN = 4; @@ -101,16 +105,26 @@ void GreCodec::get_protocol_ids(std::vector& v) * see RFCs 1701, 2784 and 2637 */ -bool GreCodec::encode(const uint8_t* const raw_in, const uint16_t raw_len, - EncState& enc, Buffer& buf, Flow*) - +void GreCodec::update(const ip::IpApi& api, const EncodeFlags /*flags*/, uint8_t* raw_pkt, + uint16_t lyr_len, uint32_t& updated_len) { - if (raw_len > GRE_HEADER_LEN) + UNUSED(api); + gre::GREHdr* const greh = reinterpret_cast(raw_pkt); + + updated_len += lyr_len; + + if (GRE_CHKSUM(greh)) { - ErrorMessage("Invalid GRE header length: %u",raw_len); - return false; + assert(lyr_len >= 6); + // Checksum field is zero for computing checksum + *(uint16_t*)(raw_pkt + 4) = 0; + *(uint16_t*)(raw_pkt + 4) = checksum::cksum_add((uint16_t*)raw_pkt, updated_len); } +} +bool GreCodec::encode(const uint8_t* const raw_in, const uint16_t raw_len, + EncState& enc, Buffer& buf, Flow*) +{ if (!buf.allocate(raw_len)) return false; @@ -119,7 +133,27 @@ bool GreCodec::encode(const uint8_t* const raw_in, const uint16_t raw_len, enc.next_proto = IpProtocol::GRE; enc.next_ethertype = greh_out->proto(); - GRE_CHKSUM(greh_out); + if (GRE_SEQ(greh_out)) + { + uint16_t len = 4; // Flags, version and protocol + + if (GRE_CHKSUM(greh_out)) + len += 4; + + if (GRE_KEY(greh_out)) + len += 4; + + *(uint32_t*)(buf.data() + len) += ntohl(1); + } + + if (GRE_CHKSUM(greh_out)) + { + assert(raw_len >= 6); + // Checksum field is zero for computing checksum + *(uint16_t*)(buf.data() + 4) = 0; + *(uint16_t*)(buf.data() + 4) = checksum::cksum_add((uint16_t*)buf.data(), + buf.size()); + } return true; }