Bug 1528 - BindToNetDevice not working for IPv6 sockets
authorTommaso Pecorella <tommaso.pecorella@unifi.it>
Wed, 28 Nov 2012 21:32:28 +0100
changeset 9148 9c37ec6053bd
parent 9147 e9af93287335
child 9154 e2048877ac28
Bug 1528 - BindToNetDevice not working for IPv6 sockets
src/internet/model/ipv6-end-point-demux.cc
src/internet/model/ipv6-end-point.cc
src/internet/model/ipv6-end-point.h
src/internet/model/ipv6-raw-socket-impl.cc
--- a/src/internet/model/ipv6-end-point-demux.cc	Sun Nov 11 16:29:57 2012 +0100
+++ b/src/internet/model/ipv6-end-point-demux.cc	Wed Nov 28 21:32:28 2012 +0100
@@ -195,6 +195,18 @@
           continue;
         }
 
+      if (endP->GetBoundNetDevice ())
+        {
+          if (endP->GetBoundNetDevice () != incomingInterface->GetDevice ())
+            {
+              NS_LOG_LOGIC ("Skipping endpoint " << &endP
+                                                 << " because endpoint is bound to specific device and"
+                                                 << endP->GetBoundNetDevice ()
+                                                 << " does not match packet device " << incomingInterface->GetDevice ());
+              continue;
+            }
+        }
+
       /*    Ipv6Address incomingInterfaceAddr = incomingInterface->GetAddress (); */
       NS_LOG_DEBUG ("dest addr " << daddr);
 
--- a/src/internet/model/ipv6-end-point.cc	Sun Nov 11 16:29:57 2012 +0100
+++ b/src/internet/model/ipv6-end-point.cc	Wed Nov 28 21:32:28 2012 +0100
@@ -78,6 +78,17 @@
   return m_peerPort;
 }
 
+void Ipv6EndPoint::BindToNetDevice (Ptr<NetDevice> netdevice)
+{
+  m_boundnetdevice = netdevice;
+  return;
+}
+
+Ptr<NetDevice> Ipv6EndPoint::GetBoundNetDevice (void)
+{
+  return m_boundnetdevice;
+}
+
 void Ipv6EndPoint::SetPeer (Ipv6Address addr, uint16_t port)
 {
   m_peerAddr = addr;
--- a/src/internet/model/ipv6-end-point.h	Sun Nov 11 16:29:57 2012 +0100
+++ b/src/internet/model/ipv6-end-point.h	Wed Nov 28 21:32:28 2012 +0100
@@ -26,6 +26,7 @@
 #include "ns3/ipv6-address.h"
 #include "ns3/callback.h"
 #include "ns3/ipv6-header.h"
+#include "ns3/net-device.h"
 
 namespace ns3
 {
@@ -96,6 +97,38 @@
   void SetPeer (Ipv6Address addr, uint16_t port);
 
   /**
+   * \brief Bind a socket to specific device.
+   *
+   * This method corresponds to using setsockopt() SO_BINDTODEVICE
+   * of real network or BSD sockets.   If set on a socket, this option will
+   * force packets to leave the bound device regardless of the device that
+   * IP routing would naturally choose.  In the receive direction, only
+   * packets received from the bound interface will be delivered.
+   *
+   * This option has no particular relationship to binding sockets to
+   * an address via Socket::Bind ().  It is possible to bind sockets to a
+   * specific IP address on the bound interface by calling both
+   * Socket::Bind (address) and Socket::BindToNetDevice (device), but it
+   * is also possible to bind to mismatching device and address, even if
+   * the socket can not receive any packets as a result.
+   *
+   * \param netdevice Pointer to Netdevice of desired interface
+   * \returns nothing
+   */
+  void BindToNetDevice (Ptr<NetDevice> netdevice);
+
+  /**
+   * \brief Returns socket's bound netdevice, if any.
+   *
+   * This method corresponds to using getsockopt() SO_BINDTODEVICE
+   * of real network or BSD sockets.
+   *
+   *
+   * \returns Pointer to interface.
+   */
+  Ptr<NetDevice> GetBoundNetDevice (void);
+
+  /**
    * \brief Set the reception callback.
    * \param callback callback function
    */
@@ -176,6 +209,11 @@
   uint16_t m_peerPort;
 
   /**
+   * \brief The NetDevice the EndPoint is bound to (if any).
+   */
+  Ptr<NetDevice> m_boundnetdevice;
+
+  /**
    * \brief The RX callback.
    */
   Callback<void, Ptr<Packet>, Ipv6Header, uint16_t> m_rxCallback;
--- a/src/internet/model/ipv6-raw-socket-impl.cc	Sun Nov 11 16:29:57 2012 +0100
+++ b/src/internet/model/ipv6-raw-socket-impl.cc	Wed Nov 28 21:32:28 2012 +0100
@@ -317,6 +317,15 @@
       return false;
     }
 
+  Ptr<NetDevice> boundNetDevice = Socket::GetBoundNetDevice();
+  if (boundNetDevice)
+    {
+      if (boundNetDevice != device)
+        {
+          return false;
+        }
+    }
+
   if ((m_src == Ipv6Address::GetAny () || hdr.GetDestinationAddress () == m_src) && 
       (m_dst == Ipv6Address::GetAny () || hdr.GetSourceAddress () == m_dst) &&
       hdr.GetNextHeader () == m_protocol)