From 0950f7f943d4340a2332e7ea0bc4be29bab8ac8d Mon Sep 17 00:00:00 2001 From: Tommaso Pecorella Date: Tue, 9 Sep 2014 09:44:37 +0200 Subject: [PATCH] TcpOptions Deserialize should return zero if a deserialization error happens --- src/internet/model/tcp-header.cc | 8 ++- src/internet/model/tcp-option-rfc793.cc | 43 +++++++-------- src/internet/model/tcp-option-rfc793.h | 44 ++++++++++++++-- src/internet/model/tcp-option-ts.cc | 2 +- src/internet/model/tcp-option-ts.h | 26 +++++++-- src/internet/model/tcp-option-winscale.cc | 2 +- src/internet/model/tcp-option-winscale.h | 54 +++---------------- src/internet/model/tcp-option.cc | 2 +- src/internet/model/tcp-option.h | 64 +++++++++++++++++++---- 9 files changed, 154 insertions(+), 91 deletions(-) diff --git a/src/internet/model/tcp-header.cc b/src/internet/model/tcp-header.cc index eb73b5099..d68888edf 100644 --- a/src/internet/model/tcp-header.cc +++ b/src/internet/model/tcp-header.cc @@ -377,8 +377,12 @@ TcpHeader::Deserialize (Buffer::Iterator start) uint8_t kind = i.PeekU8 (); Ptr op = TcpOption::CreateOption (kind); - optionLen -= op->Deserialize (i); - i.Next (op->GetSerializedSize ()); + uint32_t optionSize; + optionSize = op->Deserialize (i); + + NS_ASSERT_MSG (optionSize, "Unable to Deserialize an Option of Kind " << int (kind) << ", sorry."); + optionLen -= optionSize; + i.Next (optionSize); if (op->GetKind () != TcpOption::END) { diff --git a/src/internet/model/tcp-option-rfc793.cc b/src/internet/model/tcp-option-rfc793.cc index 5e2b6b6ad..60688a393 100644 --- a/src/internet/model/tcp-option-rfc793.cc +++ b/src/internet/model/tcp-option-rfc793.cc @@ -83,7 +83,7 @@ TcpOptionEnd::Deserialize (Buffer::Iterator start) if (readKind != GetKind ()) { NS_LOG_WARN ("Malformed END option"); - return 1; + return 0; } return GetSerializedSize (); @@ -153,7 +153,7 @@ TcpOptionNOP::Deserialize (Buffer::Iterator start) if (readKind != GetKind ()) { NS_LOG_WARN ("Malformed NOP option"); - return 1; + return 0; } return GetSerializedSize (); @@ -225,7 +225,7 @@ TcpOptionMSS::Deserialize (Buffer::Iterator start) if (readKind != GetKind ()) { NS_LOG_WARN ("Malformed MSS option"); - return 1; + return 0; } uint8_t size = i.ReadU8 (); @@ -261,6 +261,8 @@ NS_OBJECT_ENSURE_REGISTERED (TcpOptionUnknown); TcpOptionUnknown::TcpOptionUnknown () : TcpOption () { + m_kind = 0xFF; + m_size = 0; } TcpOptionUnknown::~TcpOptionUnknown () @@ -292,15 +294,21 @@ TcpOptionUnknown::Print (std::ostream &os) const uint32_t TcpOptionUnknown::GetSerializedSize (void) const { - return 0; + return m_size; } void -TcpOptionUnknown::Serialize (Buffer::Iterator start) const +TcpOptionUnknown::Serialize (Buffer::Iterator i) const { - NS_LOG_WARN ("Can't Serialize an Unknown Tcp Option"); + if (m_size == 0) + { + NS_LOG_WARN ("Can't Serialize an Unknown Tcp Option"); + return; + } - (void) start; + i.WriteU8 (GetKind ()); + i.WriteU8 (GetSerializedSize ()); + i.Write (m_content, m_size-2); } uint32_t @@ -308,28 +316,21 @@ TcpOptionUnknown::Deserialize (Buffer::Iterator start) { Buffer::Iterator i = start; - uint8_t readKind = i.ReadU8 (); - NS_LOG_WARN ("Trying to Deserialize an Unknown Option of Kind=" << readKind); + m_kind = i.ReadU8 (); + NS_LOG_WARN ("Trying to Deserialize an Unknown Option of Kind " << int (m_kind)); - uint8_t size = i.ReadU8 (); + m_size = i.ReadU8 (); + NS_ASSERT_MSG ((m_size >= 2) && (m_size < 40), "Unable to parse an Unknown Option of Kind " << int (m_kind) << " with apparent size " << int (m_size)); - if (size < 2) - { - return 0; - } + i.Read (m_content, m_size-2); - for (uint8_t j = 2; j < size; ++j) - { - i.ReadU8 (); - } - - return static_cast (size); + return m_size; } uint8_t TcpOptionUnknown::GetKind (void) const { - return 100; + return m_kind; } } // namespace ns3 diff --git a/src/internet/model/tcp-option-rfc793.h b/src/internet/model/tcp-option-rfc793.h index 25adfa76a..e3e197a3d 100644 --- a/src/internet/model/tcp-option-rfc793.h +++ b/src/internet/model/tcp-option-rfc793.h @@ -25,7 +25,7 @@ namespace ns3 { /** - * Defines the TCP option of kind 0 (end of option list) as in RFC793 + * Defines the TCP option of kind 0 (end of option list) as in \RFC{793} */ class TcpOptionEnd : public TcpOption { @@ -33,6 +33,10 @@ public: TcpOptionEnd (); virtual ~TcpOptionEnd (); + /** + * \brief Get the type ID. + * \return the object TypeId + */ static TypeId GetTypeId (void); virtual TypeId GetInstanceTypeId (void) const; @@ -46,7 +50,7 @@ public: }; /** - * Defines the TCP option of kind 1 (no operation) as in RFC793 + * Defines the TCP option of kind 1 (no operation) as in \RFC{793} */ class TcpOptionNOP : public TcpOption { @@ -54,6 +58,10 @@ public: TcpOptionNOP (); virtual ~TcpOptionNOP (); + /** + * \brief Get the type ID. + * \return the object TypeId + */ static TypeId GetTypeId (void); virtual TypeId GetInstanceTypeId (void) const; @@ -66,7 +74,7 @@ public: }; /** - * Defines the TCP option of kind 2 (maximum segment size) as in RFC793 + * Defines the TCP option of kind 2 (maximum segment size) as in \RFC{793} */ class TcpOptionMSS : public TcpOption { @@ -74,6 +82,10 @@ public: TcpOptionMSS (); virtual ~TcpOptionMSS (); + /** + * \brief Get the type ID. + * \return the object TypeId + */ static TypeId GetTypeId (void); virtual TypeId GetInstanceTypeId (void) const; @@ -84,14 +96,26 @@ public: virtual uint8_t GetKind (void) const; virtual uint32_t GetSerializedSize (void) const; + /** + * \brief Get the Maximum Segment Size stored in the Option + * \return The Maximum Segment Size + */ uint16_t GetMSS (void) const; + /** + * \brief Set the Maximum Segment Size stored in the Option + * \param mss The Maximum Segment Size + */ void SetMSS (uint16_t mss); + protected: - uint16_t m_mss; // maximum segment size + uint16_t m_mss; //!< maximum segment size }; /** - * \brief An unknown tcp option + * \brief An unknown TCP option. + * + * An unknown option can be deserialized and (only if deserialized previously) + * serialized again. */ class TcpOptionUnknown : public TcpOption { @@ -99,6 +123,10 @@ public: TcpOptionUnknown (); virtual ~TcpOptionUnknown (); + /** + * \brief Get the type ID. + * \return the object TypeId + */ static TypeId GetTypeId (void); virtual TypeId GetInstanceTypeId (void) const; @@ -108,6 +136,12 @@ public: virtual uint8_t GetKind (void) const; virtual uint32_t GetSerializedSize (void) const; + +private: + uint8_t m_kind; //!< The unknown option kind + uint32_t m_size; //!< The unknown option size + uint8_t m_content[40]; //!< The option data + }; } // namespace ns3 diff --git a/src/internet/model/tcp-option-ts.cc b/src/internet/model/tcp-option-ts.cc index 66e5edbd2..6ff06df87 100644 --- a/src/internet/model/tcp-option-ts.cc +++ b/src/internet/model/tcp-option-ts.cc @@ -84,7 +84,7 @@ TcpOptionTS::Deserialize (Buffer::Iterator start) if (readKind != GetKind ()) { NS_LOG_WARN ("Malformed Timestamp option"); - return 1; + return 0; } uint8_t size = i.ReadU8 (); diff --git a/src/internet/model/tcp-option-ts.h b/src/internet/model/tcp-option-ts.h index 03ec189b9..8b85be130 100644 --- a/src/internet/model/tcp-option-ts.h +++ b/src/internet/model/tcp-option-ts.h @@ -27,7 +27,7 @@ namespace ns3 { /** - * Defines the TCP option of kind 8 (timestamp option) as in RFC1323 + * Defines the TCP option of kind 8 (timestamp option) as in \RFC{1323} */ class TcpOptionTS : public TcpOption @@ -36,6 +36,10 @@ public: TcpOptionTS (); virtual ~TcpOptionTS (); + /** + * \brief Get the type ID. + * \return the object TypeId + */ static TypeId GetTypeId (void); virtual TypeId GetInstanceTypeId (void) const; @@ -46,9 +50,25 @@ public: virtual uint8_t GetKind (void) const; virtual uint32_t GetSerializedSize (void) const; + /** + * \brief Get the timestamp stored in the Option + * \return the timestamp + */ uint32_t GetTimestamp (void) const; + /** + * \brief Get the timestamp echo stored in the Option + * \return the timestamp echo + */ uint32_t GetEcho (void) const; + /** + * \brief Set the timestamp stored in the Option + * \param ts the timestamp + */ void SetTimestamp (uint32_t ts); + /** + * \brief Set the timestamp echo stored in the Option + * \param ts the timestamp echo + */ void SetEcho (uint32_t ts); /** @@ -79,8 +99,8 @@ public: static Time ElapsedTimeFromTsValue (uint32_t echoTime); protected: - uint32_t m_timestamp; // local timestamp - uint32_t m_echo; // echo timestamp + uint32_t m_timestamp; //!< local timestamp + uint32_t m_echo; //!< echo timestamp }; } // namespace ns3 diff --git a/src/internet/model/tcp-option-winscale.cc b/src/internet/model/tcp-option-winscale.cc index 03d1e225e..96cda0f5f 100644 --- a/src/internet/model/tcp-option-winscale.cc +++ b/src/internet/model/tcp-option-winscale.cc @@ -83,7 +83,7 @@ TcpOptionWinScale::Deserialize (Buffer::Iterator start) if (readKind != GetKind ()) { NS_LOG_WARN ("Malformed Window Scale option"); - return 1; + return 0; } uint8_t size = i.ReadU8 (); NS_ASSERT (size == 3); diff --git a/src/internet/model/tcp-option-winscale.h b/src/internet/model/tcp-option-winscale.h index f0dd3aa32..8400d74b2 100644 --- a/src/internet/model/tcp-option-winscale.h +++ b/src/internet/model/tcp-option-winscale.h @@ -27,14 +27,14 @@ namespace ns3 { /** - * \brief Defines the TCP option of kind 3 (window scale option) as in RFC1323 + * \brief Defines the TCP option of kind 3 (window scale option) as in \RFC{1323} * * For more efficient use of high bandwidth networks, a larger TCP window size * may be used. The TCP window size field controls the flow of data and its * value is limited to between 2 and 65,535 bytes. * * Since the size field cannot be expanded, a scaling factor is used. - * The TCP window scale option, as defined in RFC 1323, is an option used + * The TCP window scale option, as defined in \RFC{1323}, is an option used * to increase the maximum window size from 65,535 bytes to 1 gigabyte. * Scaling up to larger window sizes is a part of what is necessary for TCP Tuning. * @@ -48,61 +48,21 @@ namespace ns3 { class TcpOptionWinScale : public TcpOption { public: + /** + * \brief Get the type ID. + * \return the object TypeId + */ static TypeId GetTypeId (void); virtual TypeId GetInstanceTypeId (void) const; - /** - * \brief Create the option - * - * The scale is initialized with a 0U value. - */ TcpOptionWinScale (); - - /** - * \brief Deconstructor - */ virtual ~TcpOptionWinScale (); - /** - * \brief Print the option to a ostream - * - * Only the window scale (uint8_t) is printed out. - * - * \param os Stream to which print the option to - */ virtual void Print (std::ostream &os) const; - - /** - * \brief Serialize the option to a Buffer - * - * The option writes three U8: kind, length, and the scale. - * - * \param start Buffer::Iterator to which write to - */ virtual void Serialize (Buffer::Iterator start) const; - - /** - * \brief Deserialize the option from a Buffer - * - * The option read two U8: length, and the scale. Kind SHOULD be read - * before call this method. - * - * \param start Buffer::Iterator to which read from - */ virtual uint32_t Deserialize (Buffer::Iterator start); - /** - * \brief Get the kind value for this option - * - * \return Fixed value, TcpOption::WINSCALE - */ virtual uint8_t GetKind (void) const; - - /** - * \brief Get the serialized size of the option - * - * \return Fixed value, 3 - */ virtual uint32_t GetSerializedSize (void) const; /** @@ -114,7 +74,7 @@ public: /** * \brief Set the scale option * - * The scale option SHOULD be <= 14 (as RFC). + * The scale option SHOULD be <= 14 (as \RFC{1323}). * * \param scale Scale factor */ diff --git a/src/internet/model/tcp-option.cc b/src/internet/model/tcp-option.cc index 8d056af15..ccbdebd35 100644 --- a/src/internet/model/tcp-option.cc +++ b/src/internet/model/tcp-option.cc @@ -74,7 +74,7 @@ TcpOption::CreateOption (uint8_t kind) { TcpOption::WINSCALE, TcpOptionWinScale::GetTypeId () } }; - for (unsigned int i = 0; i < sizeof(toTid) / sizeof(kindToTid); ++i) + for (unsigned int i = 0; i < sizeof (toTid) / sizeof (kindToTid); ++i) { if (toTid[i].kind == kind) { diff --git a/src/internet/model/tcp-option.h b/src/internet/model/tcp-option.h index d1d54c01e..7b474b0fb 100644 --- a/src/internet/model/tcp-option.h +++ b/src/internet/model/tcp-option.h @@ -37,28 +37,72 @@ public: TcpOption (); virtual ~TcpOption (); + /** + * \brief Get the type ID. + * \return the object TypeId + */ static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + /** + * The option Kind, as defined in the respective RFCs. + */ enum Kind { - END = 0, - NOP = 1, - MSS = 2, - WINSCALE = 3, - SACK_PERM = 4, - SACK = 5, - TS = 8 + END = 0, //!< END + NOP = 1, //!< NOP + MSS = 2, //!< MSS + WINSCALE = 3, //!< WINSCALE + SACK_PERM = 4,//!< SACK_PERM + SACK = 5, //!< SACK + TS = 8 //!< TS }; + /** + * \brief Print the Option contents + * \param os the output stream + */ virtual void Print (std::ostream &os) const = 0; + /** + * \brief Serialize the Option to a buffer iterator + * \param start the buffer iterator + */ virtual void Serialize (Buffer::Iterator start) const = 0; + + /** + * \brief Deserialize the Option from a buffer iterator + * \param start the buffer iterator + * \returns the number of deserialized bytes + */ virtual uint32_t Deserialize (Buffer::Iterator start) = 0; - virtual uint8_t GetKind (void) const = 0; // Get the `kind' (as in RFC793) of this option - virtual uint32_t GetSerializedSize (void) const = 0; // Get the total length of this option, >= 1 + /** + * \brief Get the `kind' (as in \RFC{793}) of this option + * \return the Option Kind + */ + virtual uint8_t GetKind (void) const = 0; + /** + * \brief Returns number of bytes required for Option + * serialization. + * + * \returns number of bytes required for Option + * serialization + */ + virtual uint32_t GetSerializedSize (void) const = 0; - static Ptr CreateOption (uint8_t kind); // Factory method for all options + /** + * \brief Creates an option + * \param kind the option kind + * \return the requested option or an ns3::UnknownOption if the option is not supported + */ + static Ptr CreateOption (uint8_t kind); + + /** + * \brief Check if the option is implemented + * \param kind the Option kind + * \return true if the option is known + */ static bool IsKindKnown (uint8_t kind); };