A Discrete-Event Network Simulator
API
ipv4-end-point-demux.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 
21 #include "ipv4-end-point-demux.h"
22 #include "ipv4-end-point.h"
23 #include "ipv4-interface-address.h"
24 #include "ns3/log.h"
25 
26 
27 namespace ns3 {
28 
29 NS_LOG_COMPONENT_DEFINE ("Ipv4EndPointDemux");
30 
32  : m_ephemeral (49152), m_portLast (65535), m_portFirst (49152)
33 {
34  NS_LOG_FUNCTION (this);
35 }
36 
38 {
39  NS_LOG_FUNCTION (this);
40  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
41  {
42  Ipv4EndPoint *endPoint = *i;
43  delete endPoint;
44  }
45  m_endPoints.clear ();
46 }
47 
48 bool
50 {
51  NS_LOG_FUNCTION (this << port);
52  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
53  {
54  if ((*i)->GetLocalPort () == port)
55  {
56  return true;
57  }
58  }
59  return false;
60 }
61 
62 bool
64 {
65  NS_LOG_FUNCTION (this << addr << port);
66  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
67  {
68  if ((*i)->GetLocalPort () == port &&
69  (*i)->GetLocalAddress () == addr &&
70  (*i)->GetBoundNetDevice () == boundNetDevice)
71  {
72  return true;
73  }
74  }
75  return false;
76 }
77 
80 {
81  NS_LOG_FUNCTION (this);
82  uint16_t port = AllocateEphemeralPort ();
83  if (port == 0)
84  {
85  NS_LOG_WARN ("Ephemeral port allocation failed.");
86  return 0;
87  }
88  Ipv4EndPoint *endPoint = new Ipv4EndPoint (Ipv4Address::GetAny (), port);
89  m_endPoints.push_back (endPoint);
90  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
91  return endPoint;
92 }
93 
96 {
97  NS_LOG_FUNCTION (this << address);
98  uint16_t port = AllocateEphemeralPort ();
99  if (port == 0)
100  {
101  NS_LOG_WARN ("Ephemeral port allocation failed.");
102  return 0;
103  }
104  Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port);
105  m_endPoints.push_back (endPoint);
106  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
107  return endPoint;
108 }
109 
110 Ipv4EndPoint *
112 {
113  NS_LOG_FUNCTION (this << port << boundNetDevice);
114 
115  return Allocate (boundNetDevice, Ipv4Address::GetAny (), port);
116 }
117 
118 Ipv4EndPoint *
120 {
121  NS_LOG_FUNCTION (this << address << port << boundNetDevice);
122  if (LookupLocal (boundNetDevice, address, port) || LookupLocal (0, address, port))
123  {
124  NS_LOG_WARN ("Duplicated endpoint.");
125  return 0;
126  }
127  Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port);
128  m_endPoints.push_back (endPoint);
129  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
130  return endPoint;
131 }
132 
133 Ipv4EndPoint *
135  Ipv4Address localAddress, uint16_t localPort,
136  Ipv4Address peerAddress, uint16_t peerPort)
137 {
138  NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort << boundNetDevice);
139  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
140  {
141  if ((*i)->GetLocalPort () == localPort &&
142  (*i)->GetLocalAddress () == localAddress &&
143  (*i)->GetPeerPort () == peerPort &&
144  (*i)->GetPeerAddress () == peerAddress &&
145  ((*i)->GetBoundNetDevice () == boundNetDevice || (*i)->GetBoundNetDevice () == 0))
146  {
147  NS_LOG_WARN ("Duplicated endpoint.");
148  return 0;
149  }
150  }
151  Ipv4EndPoint *endPoint = new Ipv4EndPoint (localAddress, localPort);
152  endPoint->SetPeer (peerAddress, peerPort);
153  m_endPoints.push_back (endPoint);
154 
155  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
156 
157  return endPoint;
158 }
159 
160 void
162 {
163  NS_LOG_FUNCTION (this << endPoint);
164  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
165  {
166  if (*i == endPoint)
167  {
168  delete endPoint;
169  m_endPoints.erase (i);
170  break;
171  }
172  }
173 }
174 
175 /*
176  * return list of all available Endpoints
177  */
180 {
181  NS_LOG_FUNCTION (this);
182  EndPoints ret;
183 
184  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
185  {
186  Ipv4EndPoint* endP = *i;
187  ret.push_back (endP);
188  }
189  return ret;
190 }
191 
192 
193 /*
194  * If we have an exact match, we return it.
195  * Otherwise, if we find a generic match, we return it.
196  * Otherwise, we return 0.
197  */
199 Ipv4EndPointDemux::Lookup (Ipv4Address daddr, uint16_t dport,
200  Ipv4Address saddr, uint16_t sport,
201  Ptr<Ipv4Interface> incomingInterface)
202 {
203  NS_LOG_FUNCTION (this << daddr << dport << saddr << sport << incomingInterface);
204 
205  EndPoints retval1; // Matches exact on local port, wildcards on others
206  EndPoints retval2; // Matches exact on local port/adder, wildcards on others
207  EndPoints retval3; // Matches all but local address
208  EndPoints retval4; // Exact match on all 4
209 
210  NS_LOG_DEBUG ("Looking up endpoint for destination address " << daddr << ":" << dport);
211  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
212  {
213  Ipv4EndPoint* endP = *i;
214 
215  NS_LOG_DEBUG ("Looking at endpoint dport=" << endP->GetLocalPort ()
216  << " daddr=" << endP->GetLocalAddress ()
217  << " sport=" << endP->GetPeerPort ()
218  << " saddr=" << endP->GetPeerAddress ());
219 
220  if (!endP->IsRxEnabled ())
221  {
222  NS_LOG_LOGIC ("Skipping endpoint " << &endP
223  << " because endpoint can not receive packets");
224  continue;
225  }
226 
227  if (endP->GetLocalPort () != dport)
228  {
229  NS_LOG_LOGIC ("Skipping endpoint " << &endP
230  << " because endpoint dport "
231  << endP->GetLocalPort ()
232  << " does not match packet dport " << dport);
233  continue;
234  }
235  if (endP->GetBoundNetDevice ())
236  {
237  if (endP->GetBoundNetDevice () != incomingInterface->GetDevice ())
238  {
239  NS_LOG_LOGIC ("Skipping endpoint " << &endP
240  << " because endpoint is bound to specific device and"
241  << endP->GetBoundNetDevice ()
242  << " does not match packet device " << incomingInterface->GetDevice ());
243  continue;
244  }
245  }
246 
247  bool localAddressMatchesExact = false;
248  bool localAddressIsAny = false;
249  bool localAddressIsSubnetAny = false;
250 
251  // We have 3 cases:
252  // 1) Exact local / destination address match
253  // 2) Local endpoint bound to Any -> matches anything
254  // 3) Local endpoint bound to x.y.z.0 -> matches Subnet-directed broadcast packet (e.g., x.y.z.255 in a /24 net) and direct destination match.
255 
256  if (endP->GetLocalAddress () == daddr)
257  {
258  // Case 1:
259  localAddressMatchesExact = true;
260  }
261  else if (endP->GetLocalAddress () == Ipv4Address::GetAny ())
262  {
263  // Case 2:
264  localAddressIsAny = true;
265  }
266  else
267  {
268  // Case 3:
269  for (uint32_t i = 0; i < incomingInterface->GetNAddresses (); i++)
270  {
271  Ipv4InterfaceAddress addr = incomingInterface->GetAddress (i);
272 
273  Ipv4Address addrNetpart = addr.GetLocal ().CombineMask (addr.GetMask ());
274  if (endP->GetLocalAddress () == addrNetpart)
275  {
276  NS_LOG_LOGIC ("Endpoint is SubnetDirectedAny " << endP->GetLocalAddress () << "/" << addr.GetMask ().GetPrefixLength ());
277 
278  Ipv4Address daddrNetPart = daddr.CombineMask (addr.GetMask ());
279  if (addrNetpart == daddrNetPart)
280  {
281  localAddressIsSubnetAny = true;
282  }
283  }
284  }
285 
286  // if no match here, keep looking
287  if (!localAddressIsSubnetAny)
288  continue;
289  }
290 
291  bool remotePortMatchesExact = endP->GetPeerPort () == sport;
292  bool remotePortMatchesWildCard = endP->GetPeerPort () == 0;
293  bool remoteAddressMatchesExact = endP->GetPeerAddress () == saddr;
294  bool remoteAddressMatchesWildCard = endP->GetPeerAddress () == Ipv4Address::GetAny ();
295 
296  // If remote does not match either with exact or wildcard,
297  // skip this one
298  if (!(remotePortMatchesExact || remotePortMatchesWildCard))
299  continue;
300  if (!(remoteAddressMatchesExact || remoteAddressMatchesWildCard))
301  continue;
302 
303  bool localAddressMatchesWildCard = localAddressIsAny || localAddressIsSubnetAny;
304 
305  if (localAddressMatchesExact && remoteAddressMatchesExact && remotePortMatchesExact)
306  { // All 4 match - this is the case of an open TCP connection, for example.
307  NS_LOG_LOGIC ("Found an endpoint for case 4, adding " << endP->GetLocalAddress () << ":" << endP->GetLocalPort ());
308  retval4.push_back (endP);
309  }
310  if (localAddressMatchesWildCard && remoteAddressMatchesExact && remotePortMatchesExact)
311  { // All but local address - no idea what this case could be.
312  NS_LOG_LOGIC ("Found an endpoint for case 3, adding " << endP->GetLocalAddress () << ":" << endP->GetLocalPort ());
313  retval3.push_back (endP);
314  }
315  if (localAddressMatchesExact && remoteAddressMatchesWildCard && remotePortMatchesWildCard)
316  { // Only local port and local address matches exactly - Not yet opened connection
317  NS_LOG_LOGIC ("Found an endpoint for case 2, adding " << endP->GetLocalAddress () << ":" << endP->GetLocalPort ());
318  retval2.push_back (endP);
319  }
320  if (localAddressMatchesWildCard && remoteAddressMatchesWildCard && remotePortMatchesWildCard)
321  { // Only local port matches exactly - Endpoint open to "any" connection
322  NS_LOG_LOGIC ("Found an endpoint for case 1, adding " << endP->GetLocalAddress () << ":" << endP->GetLocalPort ());
323  retval1.push_back (endP);
324  }
325  }
326 
327  // Here we find the most exact match
328  EndPoints retval;
329  if (!retval4.empty ()) retval = retval4;
330  else if (!retval3.empty ()) retval = retval3;
331  else if (!retval2.empty ()) retval = retval2;
332  else retval = retval1;
333 
334  NS_ABORT_MSG_IF (retval.size () > 1, "Too many endpoints - perhaps you created too many sockets without binding them to different NetDevices.");
335  return retval; // might be empty if no matches
336 }
337 
338 Ipv4EndPoint *
340  uint16_t dport,
341  Ipv4Address saddr,
342  uint16_t sport)
343 {
344  NS_LOG_FUNCTION (this << daddr << dport << saddr << sport);
345 
346  // this code is a copy/paste version of an old BSD ip stack lookup
347  // function.
348  uint32_t genericity = 3;
349  Ipv4EndPoint *generic = 0;
350  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
351  {
352  if ((*i)->GetLocalPort () != dport)
353  {
354  continue;
355  }
356  if ((*i)->GetLocalAddress () == daddr &&
357  (*i)->GetPeerPort () == sport &&
358  (*i)->GetPeerAddress () == saddr)
359  {
360  /* this is an exact match. */
361  return *i;
362  }
363  uint32_t tmp = 0;
364  if ((*i)->GetLocalAddress () == Ipv4Address::GetAny ())
365  {
366  tmp++;
367  }
368  if ((*i)->GetPeerAddress () == Ipv4Address::GetAny ())
369  {
370  tmp++;
371  }
372  if (tmp < genericity)
373  {
374  generic = (*i);
375  genericity = tmp;
376  }
377  }
378  return generic;
379 }
380 uint16_t
382 {
383  // Similar to counting up logic in netinet/in_pcb.c
384  NS_LOG_FUNCTION (this);
385  uint16_t port = m_ephemeral;
386  int count = m_portLast - m_portFirst;
387  do
388  {
389  if (count-- < 0)
390  {
391  return 0;
392  }
393  ++port;
394  if (port < m_portFirst || port > m_portLast)
395  {
396  port = m_portFirst;
397  }
398  } while (LookupPortLocal (port));
399  m_ephemeral = port;
400  return port;
401 }
402 
403 } // namespace ns3
404 
static Ipv4Address GetAny(void)
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
bool IsRxEnabled(void)
Checks if the endpoint can receive packets.
EndPoints GetAllEndPoints(void)
Get the entire list of end points registered.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
uint16_t m_ephemeral
The ephemeral port.
bool LookupPortLocal(uint16_t port)
Lookup for port local.
uint16_t m_portFirst
The first ephemeral port.
Ipv4InterfaceAddress GetAddress(uint32_t index) const
uint16_t port
Definition: dsdv-manet.cc:45
bool LookupLocal(Ptr< NetDevice > boundNetDevice, Ipv4Address addr, uint16_t port)
Lookup for address and port.
Ipv4Address CombineMask(Ipv4Mask const &mask) const
Combine this address with a network mask.
Ipv4Address GetLocalAddress(void)
Get the local address.
Ipv4Mask GetMask(void) const
Get the network mask.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
uint16_t m_portLast
The last ephemeral port.
Ptr< NetDevice > GetBoundNetDevice(void)
Returns socket&#39;s bound netdevice, if any.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
address
Definition: first.py:44
Ptr< NetDevice > GetDevice(void) const
Ipv4EndPoint * SimpleLookup(Ipv4Address daddr, uint16_t dport, Ipv4Address saddr, uint16_t sport)
simple lookup for a match with all the parameters.
void SetPeer(Ipv4Address address, uint16_t port)
Set the peer information (address and port).
EndPoints Lookup(Ipv4Address daddr, uint16_t dport, Ipv4Address saddr, uint16_t sport, Ptr< Ipv4Interface > incomingInterface)
lookup for a match with all the parameters.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
std::list< Ipv4EndPoint * > EndPoints
Container of the IPv4 endpoints.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
a class to store IPv4 address information on an interface
uint16_t GetLocalPort(void)
Get the local port.
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:265
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
Ipv4Address GetPeerAddress(void)
Get the peer address.
uint16_t GetPeerPort(void)
Get the peer port.
Ipv4Address GetLocal(void) const
Get the local address.
uint16_t GetPrefixLength(void) const
std::list< Ipv4EndPoint * >::iterator EndPointsI
Iterator to the container of the IPv4 endpoints.
uint32_t GetNAddresses(void) const
void DeAllocate(Ipv4EndPoint *endPoint)
Remove a end point.
EndPoints m_endPoints
A list of IPv4 end points.
uint16_t AllocateEphemeralPort(void)
Allocate an ephemeral port.
A representation of an internet endpoint/connection.
Ipv4EndPoint * Allocate(void)
Allocate a Ipv4EndPoint.