diff --git a/src/internet/model/tcp-l4-protocol.cc b/src/internet/model/tcp-l4-protocol.cc index 8dc69a6a5..12409c36d 100644 --- a/src/internet/model/tcp-l4-protocol.cc +++ b/src/internet/model/tcp-l4-protocol.cc @@ -337,19 +337,14 @@ TcpL4Protocol::ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl, } enum IpL4Protocol::RxStatus -TcpL4Protocol::Receive (Ptr packet, - Ipv4Header const &incomingIpHeader, - Ptr incomingInterface) +TcpL4Protocol::PacketReceived(Ptr packet, TcpHeader &incomingTcpHeader, + Address source, Address destination) { - NS_LOG_FUNCTION (this << packet << incomingIpHeader << incomingInterface); - TcpHeader incomingTcpHeader; if(Node::ChecksumEnabled ()) { incomingTcpHeader.EnableChecksums (); - incomingTcpHeader.InitializeChecksum (incomingIpHeader.GetSource (), - incomingIpHeader.GetDestination (), - PROT_NUMBER); + incomingTcpHeader.InitializeChecksum (source, destination, PROT_NUMBER); } packet->PeekHeader (incomingTcpHeader); @@ -366,6 +361,63 @@ TcpL4Protocol::Receive (Ptr packet, return IpL4Protocol::RX_CSUM_FAILED; } + return IpL4Protocol::RX_OK; +} + +void +TcpL4Protocol::NoEndPointsFound(const TcpHeader &incomingHeader, + const Address &incomingSAddr, + const Address &incomingDAddr) +{ + if (! (incomingHeader.GetFlags () & TcpHeader::RST)) + { + // build a RST packet and send + Ptr rstPacket = Create (); + TcpHeader outgoingTcpHeader; + + if (incomingHeader.GetFlags () & TcpHeader::ACK) + { + // ACK bit was set + outgoingTcpHeader.SetFlags (TcpHeader::RST); + outgoingTcpHeader.SetSequenceNumber (incomingHeader.GetAckNumber ()); + } + else + { + outgoingTcpHeader.SetFlags (TcpHeader::RST | TcpHeader::ACK); + outgoingTcpHeader.SetSequenceNumber (SequenceNumber32 (0)); + outgoingTcpHeader.SetAckNumber (incomingHeader.GetSequenceNumber () + + SequenceNumber32 (1)); + } + + // Remember that parameters refer to the incoming packet; in reply, + // we need to swap src/dst + + outgoingTcpHeader.SetSourcePort (incomingHeader.GetDestinationPort ()); + outgoingTcpHeader.SetDestinationPort (incomingHeader.GetSourcePort ()); + + SendPacket (rstPacket, outgoingTcpHeader, incomingDAddr, incomingSAddr); + } +} + +enum IpL4Protocol::RxStatus +TcpL4Protocol::Receive (Ptr packet, + Ipv4Header const &incomingIpHeader, + Ptr incomingInterface) +{ + NS_LOG_FUNCTION (this << packet << incomingIpHeader << incomingInterface); + + TcpHeader incomingTcpHeader; + IpL4Protocol::RxStatus checksumControl; + + checksumControl = PacketReceived (packet, incomingTcpHeader, + incomingIpHeader.GetSource (), + incomingIpHeader.GetDestination ()); + + if (checksumControl != IpL4Protocol::RX_OK) + { + return checksumControl; + } + NS_LOG_LOGIC ("TcpL4Protocol "< packet, " source IP: " << incomingIpHeader.GetSource () << " source port: "<< incomingTcpHeader.GetSourcePort ()); - if (! (incomingTcpHeader.GetFlags () & TcpHeader::RST)) - { - // build a RST packet and send - Ptr rstPacket = Create (); - TcpHeader outgoingTcpHeader; - if (incomingTcpHeader.GetFlags () & TcpHeader::ACK) - { - // ACK bit was set - outgoingTcpHeader.SetFlags (TcpHeader::RST); - outgoingTcpHeader.SetSequenceNumber (incomingTcpHeader.GetAckNumber ()); - } - else - { - outgoingTcpHeader.SetFlags (TcpHeader::RST | TcpHeader::ACK); - outgoingTcpHeader.SetSequenceNumber (SequenceNumber32 (0)); - outgoingTcpHeader.SetAckNumber (incomingTcpHeader.GetSequenceNumber () + SequenceNumber32 (1)); - } + NoEndPointsFound (incomingTcpHeader, incomingIpHeader.GetSource(), + incomingIpHeader.GetDestination()); - outgoingTcpHeader.SetSourcePort (incomingTcpHeader.GetDestinationPort ()); - outgoingTcpHeader.SetDestinationPort (incomingTcpHeader.GetSourcePort ()); + return IpL4Protocol::RX_ENDPOINT_CLOSED; - SendPacket (rstPacket, outgoingTcpHeader, incomingIpHeader.GetDestination (), - incomingIpHeader.GetSource ()); - return IpL4Protocol::RX_ENDPOINT_CLOSED; - } - else - { - return IpL4Protocol::RX_ENDPOINT_CLOSED; - } } + NS_ASSERT_MSG (endPoints.size () == 1, "Demux returned more than one endpoint"); NS_LOG_LOGIC ("TcpL4Protocol "<ForwardUp (packet, incomingIpHeader, incomingTcpHeader.GetSourcePort (), incomingInterface); + return IpL4Protocol::RX_OK; } @@ -444,36 +475,27 @@ TcpL4Protocol::Receive (Ptr packet, incomingIpHeader.GetDestinationAddress ()); TcpHeader incomingTcpHeader; + IpL4Protocol::RxStatus checksumControl; // If we are receving a v4-mapped packet, we will re-calculate the TCP checksum // Is it worth checking every received "v6" packet to see if it is v4-mapped in // order to avoid re-calculating TCP checksums for v4-mapped packets? - if(Node::ChecksumEnabled ()) + checksumControl = PacketReceived (packet, incomingTcpHeader, + incomingIpHeader.GetSourceAddress (), + incomingIpHeader.GetDestinationAddress ()); + + if (checksumControl != IpL4Protocol::RX_OK) { - incomingTcpHeader.EnableChecksums (); - incomingTcpHeader.InitializeChecksum (incomingIpHeader.GetSourceAddress (), - incomingIpHeader.GetDestinationAddress (), PROT_NUMBER); - } - - packet->PeekHeader (incomingTcpHeader); - - NS_LOG_LOGIC ("TcpL4Protocol " << this - << " receiving seq " << incomingTcpHeader.GetSequenceNumber () - << " ack " << incomingTcpHeader.GetAckNumber () - << " flags "<< std::hex << (int)incomingTcpHeader.GetFlags () << std::dec - << " data size " << packet->GetSize ()); - - if(!incomingTcpHeader.IsChecksumOk ()) - { - NS_LOG_INFO ("Bad checksum, dropping packet!"); - return IpL4Protocol::RX_CSUM_FAILED; + return checksumControl; } NS_LOG_LOGIC ("TcpL4Protocol "<Lookup (incomingIpHeader.GetDestinationAddress (), incomingTcpHeader.GetDestinationPort (), - incomingIpHeader.GetSourceAddress (), incomingTcpHeader.GetSourcePort (),interface); + m_endPoints6->Lookup (incomingIpHeader.GetDestinationAddress (), + incomingTcpHeader.GetDestinationPort (), + incomingIpHeader.GetSourceAddress (), + incomingTcpHeader.GetSourcePort (), interface); if (endPoints.empty ()) { NS_LOG_LOGIC ("No endpoints matched on TcpL4Protocol "<< this << @@ -482,37 +504,18 @@ TcpL4Protocol::Receive (Ptr packet, " source IP: " << incomingIpHeader.GetSourceAddress () << " source port: "<< incomingTcpHeader.GetSourcePort ()); - if (!(incomingTcpHeader.GetFlags () & TcpHeader::RST)) - { - // build a RST packet and send - Ptr rstPacket = Create (); - TcpHeader outgoingTcpHeader; - if (incomingTcpHeader.GetFlags () & TcpHeader::ACK) - { - // ACK bit was set - outgoingTcpHeader.SetFlags (TcpHeader::RST); - outgoingTcpHeader.SetSequenceNumber (incomingTcpHeader.GetAckNumber ()); - } - else - { - outgoingTcpHeader.SetFlags (TcpHeader::RST | TcpHeader::ACK); - outgoingTcpHeader.SetSequenceNumber (SequenceNumber32 (0)); - outgoingTcpHeader.SetAckNumber (incomingTcpHeader.GetSequenceNumber () + SequenceNumber32 (1)); - } - outgoingTcpHeader.SetSourcePort (incomingTcpHeader.GetDestinationPort ()); - outgoingTcpHeader.SetDestinationPort (incomingTcpHeader.GetSourcePort ()); - SendPacket (rstPacket, outgoingTcpHeader, incomingIpHeader.GetDestinationAddress (), - incomingIpHeader.GetSourceAddress ()); - return IpL4Protocol::RX_ENDPOINT_CLOSED; - } - else - { - return IpL4Protocol::RX_ENDPOINT_CLOSED; - } + NoEndPointsFound (incomingTcpHeader, incomingIpHeader.GetSourceAddress (), + incomingIpHeader.GetDestinationAddress ()); + + return IpL4Protocol::RX_ENDPOINT_CLOSED; } + NS_ASSERT_MSG (endPoints.size () == 1, "Demux returned more than one endpoint"); NS_LOG_LOGIC ("TcpL4Protocol "<ForwardUp (packet, incomingIpHeader, incomingTcpHeader.GetSourcePort (), interface); + + (*endPoints.begin ())->ForwardUp (packet, incomingIpHeader, + incomingTcpHeader.GetSourcePort (), interface); + return IpL4Protocol::RX_OK; } @@ -616,7 +619,51 @@ TcpL4Protocol::SendPacket (Ptr packet, const TcpHeader &outgoing, } void -TcpL4Protocol::AddSocket(Ptr socket) +TcpL4Protocol::SendPacket (Ptr pkt, const TcpHeader &outgoing, + const Address &saddr, const Address &daddr, Ptr oif) +{ + if (Ipv4Address::IsMatchingType (saddr)) + { + NS_ASSERT (Ipv4Address::IsMatchingType (daddr)); + + SendPacket (pkt, outgoing, Ipv4Address::ConvertFrom (saddr), + Ipv4Address::ConvertFrom (daddr), oif); + + return; + } + else if (Ipv6Address::IsMatchingType (saddr)) + { + NS_ASSERT (Ipv6Address::IsMatchingType (daddr)); + + SendPacket (pkt, outgoing, Ipv6Address::ConvertFrom (saddr), + Ipv6Address::ConvertFrom (daddr), oif); + + return; + } + else if (InetSocketAddress::IsMatchingType (saddr)) + { + InetSocketAddress s = InetSocketAddress::ConvertFrom (saddr); + InetSocketAddress d = InetSocketAddress::ConvertFrom (daddr); + + SendPacket (pkt, outgoing, s.GetIpv4 (), d.GetIpv4 (), oif); + + return; + } + else if (Inet6SocketAddress::IsMatchingType (saddr)) + { + Inet6SocketAddress s = Inet6SocketAddress::ConvertFrom (saddr); + Inet6SocketAddress d = Inet6SocketAddress::ConvertFrom (daddr); + + SendPacket (pkt, outgoing, s.GetIpv6 (), d.GetIpv6 (), oif); + + return; + } + + NS_FATAL_ERROR ("Trying to send a packet without IP addresses"); +} + +void +TcpL4Protocol::AddSocket (Ptr socket) { std::vector >::iterator it = m_sockets.begin (); diff --git a/src/internet/model/tcp-l4-protocol.h b/src/internet/model/tcp-l4-protocol.h index 657d45e0d..5ed161291 100644 --- a/src/internet/model/tcp-l4-protocol.h +++ b/src/internet/model/tcp-l4-protocol.h @@ -25,8 +25,10 @@ #include "ns3/ipv4-address.h" #include "ns3/ipv6-address.h" +#include "ns3/sequence-number.h" #include "ip-l4-protocol.h" + namespace ns3 { class Node; @@ -177,7 +179,7 @@ public: * \param oif The output interface bound. Defaults to null (unspecified). */ void SendPacket (Ptr pkt, const TcpHeader &outgoing, - Ipv4Address saddr, Ipv4Address, Ptr oif = 0); + Ipv4Address saddr, Ipv4Address daddr, Ptr oif = 0); /** * \brief Send a packet via TCP (IPv6) @@ -191,6 +193,18 @@ public: void SendPacket (Ptr pkt, const TcpHeader &outgoing, Ipv6Address saddr, Ipv6Address daddr, Ptr oif = 0); + /** + * \brief Send a packet via TCP (IP-agnostic) + * + * \param pkt The packet to send + * \param outgoing The packet header + * \param saddr The source Ipv4Address + * \param daddr The destination Ipv4Address + * \param oif The output interface bound. Defaults to null (unspecified). + */ + void SendPacket (Ptr pkt, const TcpHeader &outgoing, + const Address &saddr, const Address &daddr, Ptr oif = 0); + /** * \brief Make a socket capable to being demultiplexed * @@ -244,6 +258,7 @@ public: protected: virtual void DoDispose (void); + /** * \brief Setup socket factory and callbacks when aggregated to a node * @@ -255,6 +270,36 @@ protected: */ virtual void NotifyNewAggregate (); + /** + * \brief Get the tcp header of the incoming packet and checks its checksum + * + * \param packet Received packet + * \param incomingTcpHeader At the end will contain the tcp header of the packet + * \param source Source address (who sent the packet) + * \param destination Destination address (who received the packet -- us) + * + * \return RX_CSUM_FAILED if the checksum check fails, RX_OK otherwise + */ + enum IpL4Protocol::RxStatus + PacketReceived (Ptr packet, TcpHeader &incomingTcpHeader, + Address source, Address destination); + + /** + * \brief Check if RST packet should be sent, and in case, send it + * + * The function is called when no endpoint is found for the received + * packet. So TcpL4Protocol do not know to who the packet should be + * given to. An RST packet is sent out as reply unless the received packet + * has the RST flag set. + * + * \param incomingHeader TCP header of the incoming packet + * \param incomingSAddr Source address of the incoming packet + * \param incomingDAddr Destination address of the incoming packet + * + */ + void NoEndPointsFound (const TcpHeader &incomingHeader, const Address &incomingSAddr, + const Address &incomingDAddr); + private: Ptr m_node; //!< the node this stack is associated with Ipv4EndPointDemux *m_endPoints; //!< A list of IPv4 end points.