Bug 400: allow /32 addresses to be used on IPv4 interfaces
authorTom Henderson <tomh@tomh.org>
Fri, 28 Nov 2008 06:05:27 -0800
changeset 3956 0339a8ad5983
parent 3949 016c554c4f6d
child 3957 e2feb7992608
child 3958 7658bcc28d8d
Bug 400: allow /32 addresses to be used on IPv4 interfaces
src/internet-stack/ipv4-l3-protocol.cc
src/internet-stack/udp-socket-impl.cc
src/node/ipv4-address.cc
src/node/ipv4-address.h
--- a/src/internet-stack/ipv4-l3-protocol.cc	Wed Nov 26 14:00:05 2008 -0800
+++ b/src/internet-stack/ipv4-l3-protocol.cc	Fri Nov 28 06:05:27 2008 -0800
@@ -852,6 +852,7 @@
           Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
           icmp->SendTimeExceededTtl (ipHeader, packet);
         }
+      NS_LOG_WARN ("TTL exceeded.  Drop.");
       m_dropTrace (packet);
       return;
     }  
--- a/src/internet-stack/udp-socket-impl.cc	Wed Nov 26 14:00:05 2008 -0800
+++ b/src/internet-stack/udp-socket-impl.cc	Fri Nov 28 06:05:27 2008 -0800
@@ -349,8 +349,13 @@
       }
   }
   //
-  // If dest is sent to the limited broadcast address (all ones),
-  // convert it to send a copy of the packet out of every interface
+  // If dest is set to the limited broadcast address (all ones),
+  // convert it to send a copy of the packet out of every 
+  // interface as a subnet-directed broadcast.
+  // Exception:  if the interface has a /32 address, there is no
+  // valid subnet-directed broadcast, so send it as limited broadcast
+  // Note also that some systems will only send limited broadcast packets
+  // out of the "default" interface; here we send it out all interfaces
   //
   if (dest.IsBroadcast ())
     {
@@ -359,13 +364,27 @@
         {
           Ipv4Address addri = ipv4->GetAddress (i);
           Ipv4Mask maski = ipv4->GetNetworkMask (i);
-          Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski);
-          NS_LOG_LOGIC ("Sending one copy from " << addri << " to " << bcast
-                        << " (mask is " << maski << ")");
-          m_udp->Send (p->Copy (), addri, bcast,
-                       m_endPoint->GetLocalPort (), port);
-          NotifyDataSent (p->GetSize ());
-          NotifySend (GetTxAvailable ());
+          if (maski == Ipv4Mask::GetOnes ())
+            {
+              // if the network mask is 255.255.255.255, do not convert dest
+              NS_LOG_LOGIC ("Sending one copy from " << addri << " to " << dest
+                            << " (mask is " << maski << ")");
+              m_udp->Send (p->Copy (), addri, dest,
+                           m_endPoint->GetLocalPort (), port);
+              NotifyDataSent (p->GetSize ());
+              NotifySend (GetTxAvailable ());
+            }
+          else
+            {
+              // Convert to subnet-directed broadcast
+              Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski);
+              NS_LOG_LOGIC ("Sending one copy from " << addri << " to " << bcast
+                            << " (mask is " << maski << ")");
+              m_udp->Send (p->Copy (), addri, bcast,
+                           m_endPoint->GetLocalPort (), port);
+              NotifyDataSent (p->GetSize ());
+              NotifySend (GetTxAvailable ());
+            }
         }
       NS_LOG_LOGIC ("Limited broadcast end.");
       return p->GetSize();
--- a/src/node/ipv4-address.cc	Wed Nov 26 14:00:05 2008 -0800
+++ b/src/node/ipv4-address.cc	Fri Nov 28 06:05:27 2008 -0800
@@ -77,7 +77,6 @@
   }
 }
 
-
 bool 
 Ipv4Mask::IsMatch (Ipv4Address a, Ipv4Address b) const
 {
@@ -126,6 +125,12 @@
   static Ipv4Mask zero = Ipv4Mask ("0.0.0.0");
   return zero;
 }
+Ipv4Mask
+Ipv4Mask::GetOnes (void)
+{
+  static Ipv4Mask ones = Ipv4Mask ("255.255.255.255");
+  return ones;
+}
 
 Ipv4Address::Ipv4Address ()
   : m_address (0x66666666)
@@ -164,12 +169,22 @@
 Ipv4Address 
 Ipv4Address::GetSubnetDirectedBroadcast (Ipv4Mask const &mask) const
 {
+  if (mask == Ipv4Mask::GetOnes ())
+    {
+      NS_ASSERT_MSG (false, "Trying to get subnet-directed broadcast address with an all-ones netmask");
+    }
   return Ipv4Address (Get () | mask.GetInverse ());
 }
 
 bool
 Ipv4Address::IsSubnetDirectedBroadcast (Ipv4Mask const &mask) const
 {
+  if (mask == Ipv4Mask::GetOnes ())
+    {
+      // If the mask is 255.255.255.255, there is no subnet directed
+      // broadcast for this address.
+      return false;
+    }
   return ( (Get () | mask.GetInverse ()) == Get () );
 }
 
--- a/src/node/ipv4-address.h	Wed Nov 26 14:00:05 2008 -0800
+++ b/src/node/ipv4-address.h	Fri Nov 28 06:05:27 2008 -0800
@@ -91,7 +91,7 @@
   void Serialize (uint8_t buf[4]) const;
   /**
    * \param buf buffer to read address from
-   * \returns an Ipv4Address
+   * \return an Ipv4Address
    * 
    * The input address is expected to be in network byte order format.
    */
@@ -103,8 +103,13 @@
    * \param os The output stream to which this Ipv4Address is printed
    */
   void Print (std::ostream &os) const;
-
+  /**
+    * \return true if address is 255.255.255.255; false otherwise
+    */
   bool IsBroadcast (void) const;
+  /**
+    * \return true only if address is in the range 224.0.0.0 - 239.255.255.255
+    */
   bool IsMulticast (void) const;
   /**
    * \brief Combine this address with a network mask
@@ -120,20 +125,63 @@
    * \brief Generate subnet-directed broadcast address corresponding to mask
    *
    * The subnet-directed broadcast address has the host bits set to all
-   * ones.
+   * ones.  If this method is called with a mask of 255.255.255.255,
+   * (i.e., the address is a /32 address), the program will assert, since
+   * there is no subnet associated with a /32 address.
    *
    * \param mask a network mask 
    */
   Ipv4Address GetSubnetDirectedBroadcast (Ipv4Mask const &mask) const;
+  /**
+   * \brief Generate subnet-directed broadcast address corresponding to mask
+   * 
+   * The subnet-directed broadcast address has the host bits set to all
+   * ones.  If this method is called with a mask of 255.255.255.255,
+   * (i.e., the address is a /32 address), the program will assert, since
+   * there is no subnet associated with a /32 address.
+   *
+   * \param mask a network mask 
+   * \return true if the address, when combined with the input mask, has all
+   * of its host bits set to one
+   */
   bool IsSubnetDirectedBroadcast (Ipv4Mask const &mask) const;
-
+  /**
+   * \param address an address to compare type with
+   *
+   * \return true if the type of the address stored internally
+   * is compatible with the type of the input address, false otherwise.
+   */
   static bool IsMatchingType (const Address &address);
+  /**
+   * Convert an instance of this class to a polymorphic Address instance.
+   *
+   * \return a new Address instance
+   */
   operator Address () const;
+  /**
+   * \param address a polymorphic address
+   * \return a new Ipv4Address from the polymorphic address
+   *
+   * This function performs a type check and asserts if the
+   * type of the input address is not compatible with an
+   * Ipv4Address.
+   */
   static Ipv4Address ConvertFrom (const Address &address);
-
+  /**
+   * \return the 0.0.0.0 address
+   */
   static Ipv4Address GetZero (void);
+  /**
+   * \return the 0.0.0.0 address
+   */
   static Ipv4Address GetAny (void);
+  /**
+   * \return the 255.255.255.255 address
+   */
   static Ipv4Address GetBroadcast (void);
+  /**
+   * \return the 127.0.0.1 address
+   */
   static Ipv4Address GetLoopback (void);
 
 private:
@@ -156,9 +204,17 @@
   Ipv4Mask ();
   Ipv4Mask (uint32_t mask);
   Ipv4Mask (char const *mask);
-
+  /**
+   * \param a first address to compare
+   * \param b second address to compare
+   * \return true if both addresses are equal in their masked bits, 
+   * corresponding to this mask
+   */
   bool IsMatch (Ipv4Address a, Ipv4Address b) const;
-
+  /**
+   * \param other a mask to compare 
+   * \return true if the mask equals the mask passed as input parameter
+   */
   bool IsEqual (Ipv4Mask other) const;
   /** 
    * Get the host-order 32-bit IP mask
@@ -174,11 +230,25 @@
    * \brief Return the inverse mask in host order. 
    */
   uint32_t GetInverse (void) const;
-
+  /**
+   * \brief Print this mask to the given output stream
+   *
+   * The print format is in the typical "255.255.255.0"
+   * \param os The output stream to which this Ipv4Address is printed
+   */
   void Print (std::ostream &os) const;
-
+  /**
+   * \return the 255.0.0.0 mask corresponding to a typical loopback address
+   */
   static Ipv4Mask GetLoopback (void);
+  /**
+   * \return the 0.0.0.0 mask
+   */
   static Ipv4Mask GetZero (void);
+  /**
+   * \return the 255.255.255.255 mask
+   */
+  static Ipv4Mask GetOnes (void);
 
 private:
   uint32_t m_mask;