View | Details | Raw Unified | Return to bug 2762
Collapse All | Expand All

(-)a/CHANGES.html (+11 lines)
 Lines 130-135    Link Here 
130
    <b>Previously, a socket bound to an unicast address received also subnet-directed broadcast packets. 
130
    <b>Previously, a socket bound to an unicast address received also subnet-directed broadcast packets. 
131
    This is not anymore possible</b>.
131
    This is not anymore possible</b>.
132
</li>
132
</li>
133
<li>You can now Bind as many socket as you want to an address/port. However, only <b>one</b> socket will be
134
    used to forward up an incoming packet. If more than one socket matches the incoming packet, an error at
135
    run-time will be thrown.
136
    In particular, the following cases are legal:
137
    <ul>
138
    <li> Two (or more) sockets bound to different NetDevices.</li>
139
    <li> Two (or more) sockets, one not bound to any NetDevive, and the others bound to different NetDevices.</li>
140
    </ul> 
141
    Moreover, BindToNetDevice does not anymore call Bind. In other terms, Bind and BindToNetDevice can be called
142
    in any order.
143
</li>
133
</ul>
144
</ul>
134
<h2>Changes to build system:</h2>
145
<h2>Changes to build system:</h2>
135
<ul>
146
<ul>
(-)a/src/internet/model/ipv4-end-point-demux.cc (-14 / +57 lines)
 Lines 120-127    Link Here 
120
  NS_LOG_FUNCTION (this << address << port);
120
  NS_LOG_FUNCTION (this << address << port);
121
  if (LookupLocal (address, port)) 
121
  if (LookupLocal (address, port)) 
122
    {
122
    {
123
      NS_LOG_WARN ("Duplicate address/port; failing.");
123
      NS_LOG_WARN ("Duplicated endpoint - I hope you will use BindToNetDevice later.");
124
      return 0;
125
    }
124
    }
126
  Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port);
125
  Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port);
127
  m_endPoints.push_back (endPoint);
126
  m_endPoints.push_back (endPoint);
 Lines 141-149    Link Here 
141
          (*i)->GetPeerPort () == peerPort &&
140
          (*i)->GetPeerPort () == peerPort &&
142
          (*i)->GetPeerAddress () == peerAddress) 
141
          (*i)->GetPeerAddress () == peerAddress) 
143
        {
142
        {
144
          NS_LOG_WARN ("No way we can allocate this end-point.");
143
          NS_LOG_WARN ("Duplicated endpoint - I hope you will use BindToNetDevice later.");
145
          /* no way we can allocate this end-point. */
146
          return 0;
147
        }
144
        }
148
    }
145
    }
149
  Ipv4EndPoint *endPoint = new Ipv4EndPoint (localAddress, localPort);
146
  Ipv4EndPoint *endPoint = new Ipv4EndPoint (localAddress, localPort);
 Lines 204-209    Link Here 
204
  EndPoints retval2; // Matches exact on local port/adder, wildcards on others
201
  EndPoints retval2; // Matches exact on local port/adder, wildcards on others
205
  EndPoints retval3; // Matches all but local address
202
  EndPoints retval3; // Matches all but local address
206
  EndPoints retval4; // Exact match on all 4
203
  EndPoints retval4; // Exact match on all 4
204
  EndPoints retvalBound1; // Matches exact on local port, wildcards on others
205
  EndPoints retvalBound2; // Matches exact on local port/adder, wildcards on others
206
  EndPoints retvalBound3; // Matches all but local address
207
  EndPoints retvalBound4; // Exact match on all 4
207
208
208
  NS_LOG_DEBUG ("Looking up endpoint for destination address " << daddr << ":" << dport);
209
  NS_LOG_DEBUG ("Looking up endpoint for destination address " << daddr << ":" << dport);
209
  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) 
210
  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) 
 Lines 303-332    Link Here 
303
      if (localAddressMatchesExact && remoteAddressMatchesExact && remotePortMatchesExact)
304
      if (localAddressMatchesExact && remoteAddressMatchesExact && remotePortMatchesExact)
304
        { // All 4 match - this is the case of an open TCP connection, for example.
305
        { // All 4 match - this is the case of an open TCP connection, for example.
305
          NS_LOG_LOGIC ("Found an endpoint for case 4, adding " << endP->GetLocalAddress () << ":" << endP->GetLocalPort ());
306
          NS_LOG_LOGIC ("Found an endpoint for case 4, adding " << endP->GetLocalAddress () << ":" << endP->GetLocalPort ());
306
          retval4.push_back (endP);
307
          if (endP->GetBoundNetDevice ())
308
            {
309
              retvalBound4.push_back (endP);
310
            }
311
          else
312
            {
313
              retval4.push_back (endP);
314
            }
307
        }
315
        }
308
      if (localAddressMatchesWildCard && remoteAddressMatchesExact && remotePortMatchesExact)
316
      if (localAddressMatchesWildCard && remoteAddressMatchesExact && remotePortMatchesExact)
309
        { // All but local address - no idea what this case could be.
317
        { // All but local address - no idea what this case could be.
310
          NS_LOG_LOGIC ("Found an endpoint for case 3, adding " << endP->GetLocalAddress () << ":" << endP->GetLocalPort ());
318
          NS_LOG_LOGIC ("Found an endpoint for case 3, adding " << endP->GetLocalAddress () << ":" << endP->GetLocalPort ());
311
          retval3.push_back (endP);
319
          if (endP->GetBoundNetDevice ())
320
            {
321
              retvalBound3.push_back (endP);
322
            }
323
          else
324
            {
325
              retval3.push_back (endP);
326
            }
312
        }
327
        }
313
      if (localAddressMatchesExact && remoteAddressMatchesWildCard && remotePortMatchesWildCard)
328
      if (localAddressMatchesExact && remoteAddressMatchesWildCard && remotePortMatchesWildCard)
314
        { // Only local port and local address matches exactly - Not yet opened connection
329
        { // Only local port and local address matches exactly - Not yet opened connection
315
          NS_LOG_LOGIC ("Found an endpoint for case 2, adding " << endP->GetLocalAddress () << ":" << endP->GetLocalPort ());
330
          NS_LOG_LOGIC ("Found an endpoint for case 2, adding " << endP->GetLocalAddress () << ":" << endP->GetLocalPort ());
316
          retval2.push_back (endP);
331
          if (endP->GetBoundNetDevice ())
332
            {
333
              retvalBound2.push_back (endP);
334
            }
335
          else
336
            {
337
              retval2.push_back (endP);
338
            }
317
        }
339
        }
318
      if (localAddressMatchesWildCard && remoteAddressMatchesWildCard && remotePortMatchesWildCard)
340
      if (localAddressMatchesWildCard && remoteAddressMatchesWildCard && remotePortMatchesWildCard)
319
        { // Only local port matches exactly - Endpoint open to "any" connection
341
        { // Only local port matches exactly - Endpoint open to "any" connection
320
          NS_LOG_LOGIC ("Found an endpoint for case 1, adding " << endP->GetLocalAddress () << ":" << endP->GetLocalPort ());
342
          NS_LOG_LOGIC ("Found an endpoint for case 1, adding " << endP->GetLocalAddress () << ":" << endP->GetLocalPort ());
321
          retval1.push_back (endP);
343
          if (endP->GetBoundNetDevice ())
344
            {
345
              retvalBound1.push_back (endP);
346
            }
347
          else
348
            {
349
              retval1.push_back (endP);
350
            }
322
        }
351
        }
323
    }
352
    }
324
353
325
  // Here we find the most exact match
354
  // Here we find the most exact match, but we could still have one ambiguity
326
  if (!retval4.empty ()) return retval4;
355
  // I.e., one EndPoint not bound to any NetDevice and one bound.
327
  if (!retval3.empty ()) return retval3;
356
  // We always go for the bound one.
328
  if (!retval2.empty ()) return retval2;
357
329
  return retval1;  // might be empty if no matches
358
  EndPoints retval;
359
  if (!retvalBound4.empty ()) retval = retvalBound4;
360
  else if (!retval4.empty ()) retval = retval4;
361
  else if (!retvalBound3.empty ()) retval = retvalBound3;
362
  else if (!retval3.empty ()) retval = retval3;
363
  else if (!retvalBound2.empty ()) retval = retvalBound2;
364
  else if (!retval2.empty ()) retval = retval2;
365
  else if (!retvalBound1.empty ()) retval = retvalBound1;
366
  else retval = retval1;
367
368
  if (retval.size () > 1)
369
    {
370
      NS_ABORT_MSG ("Too many endpoints - perhaps you created too many sockets without binding them to different NetDevices.");
371
    }
372
  return retval;  // might be empty if no matches
330
}
373
}
331
374
332
Ipv4EndPoint *
375
Ipv4EndPoint *
(-)a/src/internet/model/ipv6-end-point-demux.cc (-21 / +51 lines)
 Lines 114-121    Link Here 
114
  NS_LOG_FUNCTION (this << address << port);
114
  NS_LOG_FUNCTION (this << address << port);
115
  if (LookupLocal (address, port))
115
  if (LookupLocal (address, port))
116
    {
116
    {
117
      NS_LOG_WARN ("Duplicate address/port; failing.");
117
      NS_LOG_WARN ("Duplicated endpoint - I hope you will use BindToNetDevice later.");
118
      return 0;
119
    }
118
    }
120
  Ipv6EndPoint *endPoint = new Ipv6EndPoint (address, port);
119
  Ipv6EndPoint *endPoint = new Ipv6EndPoint (address, port);
121
  m_endPoints.push_back (endPoint);
120
  m_endPoints.push_back (endPoint);
 Lines 134-142    Link Here 
134
          && (*i)->GetPeerPort () == peerPort
133
          && (*i)->GetPeerPort () == peerPort
135
          && (*i)->GetPeerAddress () == peerAddress)
134
          && (*i)->GetPeerAddress () == peerAddress)
136
        {
135
        {
137
          NS_LOG_WARN ("No way we can allocate this end-point.");
136
          NS_LOG_WARN ("Duplicated endpoint - I hope you will use BindToNetDevice later.");
138
          /* no way we can allocate this end-point. */
139
          return 0;
140
        }
137
        }
141
    }
138
    }
142
  Ipv6EndPoint *endPoint = new Ipv6EndPoint (localAddress, localPort);
139
  Ipv6EndPoint *endPoint = new Ipv6EndPoint (localAddress, localPort);
 Lines 177-182    Link Here 
177
  EndPoints retval2; /* Matches exact on local port/adder, wildcards on others */
174
  EndPoints retval2; /* Matches exact on local port/adder, wildcards on others */
178
  EndPoints retval3; /* Matches all but local address */
175
  EndPoints retval3; /* Matches all but local address */
179
  EndPoints retval4; /* Exact match on all 4 */
176
  EndPoints retval4; /* Exact match on all 4 */
177
  EndPoints retvalBound1; // Matches exact on local port, wildcards on others
178
  EndPoints retvalBound2; // Matches exact on local port/adder, wildcards on others
179
  EndPoints retvalBound3; // Matches all but local address
180
  EndPoints retvalBound4; // Exact match on all 4
180
181
181
  NS_LOG_DEBUG ("Looking up endpoint for destination address " << daddr);
182
  NS_LOG_DEBUG ("Looking up endpoint for destination address " << daddr);
182
  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
183
  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
 Lines 253-294    Link Here 
253
          && remotePeerMatchesWildCard
254
          && remotePeerMatchesWildCard
254
          && remoteAddressMatchesWildCard)
255
          && remoteAddressMatchesWildCard)
255
        { /* Only local port matches exactly */
256
        { /* Only local port matches exactly */
256
          retval1.push_back (endP);
257
          if (endP->GetBoundNetDevice ())
258
            {
259
              retvalBound1.push_back (endP);
260
            }
261
          else
262
            {
263
              retval1.push_back (endP);
264
            }
257
        }
265
        }
258
      if ((localAddressMatchesExact || (localAddressMatchesAllRouters))
266
      if ((localAddressMatchesExact || (localAddressMatchesAllRouters))
259
          && remotePeerMatchesWildCard
267
          && remotePeerMatchesWildCard
260
          && remoteAddressMatchesWildCard)
268
          && remoteAddressMatchesWildCard)
261
        { /* Only local port and local address matches exactly */
269
        { /* Only local port and local address matches exactly */
262
          retval2.push_back (endP);
270
          if (endP->GetBoundNetDevice ())
271
            {
272
              retvalBound2.push_back (endP);
273
            }
274
          else
275
            {
276
              retval2.push_back (endP);
277
            }
263
        }
278
        }
264
      if (localAddressMatchesWildCard
279
      if (localAddressMatchesWildCard
265
          && remotePeerMatchesExact
280
          && remotePeerMatchesExact
266
          && remoteAddressMatchesExact)
281
          && remoteAddressMatchesExact)
267
        { /* All but local address */
282
        { /* All but local address */
268
          retval3.push_back (endP);
283
          if (endP->GetBoundNetDevice ())
284
            {
285
              retvalBound3.push_back (endP);
286
            }
287
          else
288
            {
289
              retval3.push_back (endP);
290
            }
269
        }
291
        }
270
      if (localAddressMatchesExact
292
      if (localAddressMatchesExact
271
          && remotePeerMatchesExact
293
          && remotePeerMatchesExact
272
          && remoteAddressMatchesExact)
294
          && remoteAddressMatchesExact)
273
        { /* All 4 match */
295
        { /* All 4 match */
274
          retval4.push_back (endP);
296
          if (endP->GetBoundNetDevice ())
297
            {
298
              retvalBound4.push_back (endP);
299
            }
300
          else
301
            {
302
              retval4.push_back (endP);
303
            }
275
        }
304
        }
276
    }
305
    }
277
306
278
  /* Here we find the most exact match */
307
  EndPoints retval;
279
  if (!retval4.empty ())
308
  if (!retvalBound4.empty ()) retval = retvalBound4;
280
    {
309
  else if (!retval4.empty ()) retval = retval4;
281
      return retval4;
310
  else if (!retvalBound3.empty ()) retval = retvalBound3;
282
    }
311
  else if (!retval3.empty ()) retval = retval3;
283
  if (!retval3.empty ())
312
  else if (!retvalBound2.empty ()) retval = retvalBound2;
313
  else if (!retval2.empty ()) retval = retval2;
314
  else if (!retvalBound1.empty ()) retval = retvalBound1;
315
  else retval = retval1;
316
317
  if (retval.size () > 1)
284
    {
318
    {
285
      return retval3;
319
      NS_ABORT_MSG ("Too many endpoints - perhaps you created too many sockets without binding them to different NetDevices.");
286
    }
320
    }
287
  if (!retval2.empty ())
321
  return retval;  // might be empty if no matches
288
    {
289
      return retval2;
290
    }
291
  return retval1;  /* might be empty if no matches */
292
}
322
}
293
323
294
Ipv6EndPoint* Ipv6EndPointDemux::SimpleLookup (Ipv6Address dst, uint16_t dport, Ipv6Address src, uint16_t sport)
324
Ipv6EndPoint* Ipv6EndPointDemux::SimpleLookup (Ipv6Address dst, uint16_t dport, Ipv6Address src, uint16_t sport)
(-)a/src/internet/model/tcp-socket-base.cc (-17 / +5 lines)
 Lines 991-1017    Link Here 
991
{
991
{
992
  NS_LOG_FUNCTION (netdevice);
992
  NS_LOG_FUNCTION (netdevice);
993
  Socket::BindToNetDevice (netdevice); // Includes sanity check
993
  Socket::BindToNetDevice (netdevice); // Includes sanity check
994
  if (m_endPoint == 0)
994
  if (m_endPoint != 0)
995
    {
995
    {
996
      if (Bind () == -1)
996
      m_endPoint->BindToNetDevice (netdevice);
997
        {
998
          NS_ASSERT (m_endPoint == 0);
999
          return;
1000
        }
1001
      NS_ASSERT (m_endPoint != 0);
1002
    }
997
    }
1003
  m_endPoint->BindToNetDevice (netdevice);
998
1004
999
  if (m_endPoint6 != 0)
1005
  if (m_endPoint6 == 0)
1006
    {
1000
    {
1007
      if (Bind6 () == -1)
1001
      m_endPoint6->BindToNetDevice (netdevice);
1008
        {
1009
          NS_ASSERT (m_endPoint6 == 0);
1010
          return;
1011
        }
1012
      NS_ASSERT (m_endPoint6 != 0);
1013
    }
1002
    }
1014
  m_endPoint6->BindToNetDevice (netdevice);
1015
1003
1016
  return;
1004
  return;
1017
}
1005
}
(-)a/src/internet/model/udp-socket-impl.cc (-26 / +61 lines)
 Lines 233-238    Link Here 
233
{
233
{
234
  NS_LOG_FUNCTION_NOARGS ();
234
  NS_LOG_FUNCTION_NOARGS ();
235
  m_endPoint = m_udp->Allocate ();
235
  m_endPoint = m_udp->Allocate ();
236
  if (m_boundnetdevice)
237
    {
238
      m_endPoint->BindToNetDevice (m_boundnetdevice);
239
    }
236
  return FinishBind ();
240
  return FinishBind ();
237
}
241
}
238
242
 Lines 241-246    Link Here 
241
{
245
{
242
  NS_LOG_FUNCTION_NOARGS ();
246
  NS_LOG_FUNCTION_NOARGS ();
243
  m_endPoint6 = m_udp->Allocate6 ();
247
  m_endPoint6 = m_udp->Allocate6 ();
248
  if (m_boundnetdevice)
249
    {
250
      m_endPoint6->BindToNetDevice (m_boundnetdevice);
251
    }
244
  return FinishBind ();
252
  return FinishBind ();
245
}
253
}
246
254
 Lines 278-283    Link Here 
278
          m_errno = port ? ERROR_ADDRINUSE : ERROR_ADDRNOTAVAIL;
286
          m_errno = port ? ERROR_ADDRINUSE : ERROR_ADDRNOTAVAIL;
279
          return -1;
287
          return -1;
280
        }
288
        }
289
      if (m_boundnetdevice)
290
        {
291
          m_endPoint->BindToNetDevice (m_boundnetdevice);
292
        }
293
281
    }
294
    }
282
  else if (Inet6SocketAddress::IsMatchingType (address))
295
  else if (Inet6SocketAddress::IsMatchingType (address))
283
    {
296
    {
 Lines 307-318    Link Here 
307
          m_errno = port ? ERROR_ADDRINUSE : ERROR_ADDRNOTAVAIL;
320
          m_errno = port ? ERROR_ADDRINUSE : ERROR_ADDRNOTAVAIL;
308
          return -1;
321
          return -1;
309
        }
322
        }
323
      if (m_boundnetdevice)
324
        {
325
          m_endPoint6->BindToNetDevice (m_boundnetdevice);
326
        }
327
310
      if (ipv6.IsMulticast ())
328
      if (ipv6.IsMulticast ())
311
        {
329
        {
312
          Ptr<Ipv6L3Protocol> ipv6l3 = m_node->GetObject <Ipv6L3Protocol> ();
330
          Ptr<Ipv6L3Protocol> ipv6l3 = m_node->GetObject <Ipv6L3Protocol> ();
313
          if (ipv6l3)
331
          if (ipv6l3)
314
            {
332
            {
315
              ipv6l3->AddMulticastAddress (ipv6);
333
              if (m_boundnetdevice == 0)
334
                {
335
                  ipv6l3->AddMulticastAddress (ipv6);
336
                }
337
              else
338
                {
339
                  uint32_t index = ipv6l3->GetInterfaceForDevice (m_boundnetdevice);
340
                  ipv6l3->AddMulticastAddress (m_endPoint6->GetLocalAddress (), index);
341
                }
316
            }
342
            }
317
        }
343
        }
318
    }
344
    }
 Lines 928-964    Link Here 
928
{
954
{
929
  NS_LOG_FUNCTION (netdevice);
955
  NS_LOG_FUNCTION (netdevice);
930
956
957
  Ptr<NetDevice> oldBoundNetDevice = m_boundnetdevice;
958
931
  Socket::BindToNetDevice (netdevice); // Includes sanity check
959
  Socket::BindToNetDevice (netdevice); // Includes sanity check
932
  if (m_endPoint == 0)
960
  if (m_endPoint != 0)
933
    {
961
    {
934
      if (Bind () == -1)
962
      m_endPoint->BindToNetDevice (netdevice);
935
        {
936
          NS_ASSERT (m_endPoint == 0);
937
          return;
938
        }
939
      NS_ASSERT (m_endPoint != 0);
940
    }
963
    }
941
  m_endPoint->BindToNetDevice (netdevice);
942
964
943
  if (m_endPoint6 == 0)
965
  if (m_endPoint6 != 0)
944
    {
966
    {
945
      if (Bind6 () == -1)
967
      m_endPoint6->BindToNetDevice (netdevice);
968
969
      // The following is to fix the multicast distribution inside the node
970
      // and to upgrade it to the actual bound NetDevice.
971
      if (m_endPoint6->GetLocalAddress ().IsMulticast ())
946
        {
972
        {
947
          NS_ASSERT (m_endPoint6 == 0);
973
          Ptr<Ipv6L3Protocol> ipv6l3 = m_node->GetObject <Ipv6L3Protocol> ();
948
          return;
974
          if (ipv6l3)
949
        }
975
            {
950
      NS_ASSERT (m_endPoint6 != 0);
976
              // Cleanup old one
951
    }
977
              if (oldBoundNetDevice)
952
  m_endPoint6->BindToNetDevice (netdevice);
978
                {
953
979
                  uint32_t index = ipv6l3->GetInterfaceForDevice (oldBoundNetDevice);
954
  if (m_endPoint6->GetLocalAddress ().IsMulticast ())
980
                  ipv6l3->RemoveMulticastAddress (m_endPoint6->GetLocalAddress (), index);
955
    {
981
                }
956
      Ptr<Ipv6L3Protocol> ipv6l3 = m_node->GetObject <Ipv6L3Protocol> ();
982
              else
957
      if (ipv6l3)
983
                {
958
        {
984
                  ipv6l3->RemoveMulticastAddress (m_endPoint6->GetLocalAddress ());
959
          uint32_t index = ipv6l3->GetInterfaceForDevice (netdevice);
985
                }
960
          ipv6l3->RemoveMulticastAddress (m_endPoint6->GetLocalAddress ());
986
              // add new one
961
          ipv6l3->AddMulticastAddress (m_endPoint6->GetLocalAddress (), index);
987
              if (netdevice)
988
                {
989
                  uint32_t index = ipv6l3->GetInterfaceForDevice (netdevice);
990
                  ipv6l3->AddMulticastAddress (m_endPoint6->GetLocalAddress (), index);
991
                }
992
              else
993
                {
994
                  ipv6l3->AddMulticastAddress (m_endPoint6->GetLocalAddress ());
995
                }
996
            }
962
        }
997
        }
963
    }
998
    }
964
999
(-)a/src/network/model/socket.h (-5 / +2 lines)
 Lines 616-631    Link Here 
616
   * is also possible to bind to mismatching device and address, even if
616
   * is also possible to bind to mismatching device and address, even if
617
   * the socket can not receive any packets as a result.
617
   * the socket can not receive any packets as a result.
618
   *
618
   *
619
   * \warning BindToNetDevice should be used \a after Bind. Otherwise
619
   * \param netdevice Pointer to NetDevice of desired interface
620
   * it will perform a Bind itself.
621
   *
622
   * \param netdevice Pointer to Netdevice of desired interface
623
   * \returns nothing
620
   * \returns nothing
624
   */
621
   */
625
  virtual void BindToNetDevice (Ptr<NetDevice> netdevice);
622
  virtual void BindToNetDevice (Ptr<NetDevice> netdevice);
626
623
627
  /**
624
  /**
628
   * \brief Returns socket's bound netdevice, if any.
625
   * \brief Returns socket's bound NetDevice, if any.
629
   *
626
   *
630
   * This method corresponds to using getsockopt() SO_BINDTODEVICE
627
   * This method corresponds to using getsockopt() SO_BINDTODEVICE
631
   * of real network or BSD sockets.
628
   * of real network or BSD sockets.

Return to bug 2762