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 
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
static Ipv4Address GetAny(void)
Ipv4Address CombineMask(Ipv4Mask const &mask) const
Combine this address with a network mask.
uint16_t m_portFirst
The first ephemeral port.
EndPoints m_endPoints
A list of IPv4 end points.
uint16_t m_portLast
The last ephemeral port.
EndPoints GetAllEndPoints(void)
Get the entire list of end points registered.
std::list< Ipv4EndPoint * > EndPoints
Container of the IPv4 endpoints.
Ipv4EndPoint * SimpleLookup(Ipv4Address daddr, uint16_t dport, Ipv4Address saddr, uint16_t sport)
simple lookup for a match with all the parameters.
uint16_t AllocateEphemeralPort(void)
Allocate an ephemeral port.
bool LookupLocal(Ptr< NetDevice > boundNetDevice, Ipv4Address addr, uint16_t port)
Lookup for address and port.
Ipv4EndPoint * Allocate(void)
Allocate a Ipv4EndPoint.
uint16_t m_ephemeral
The ephemeral port.
EndPoints Lookup(Ipv4Address daddr, uint16_t dport, Ipv4Address saddr, uint16_t sport, Ptr< Ipv4Interface > incomingInterface)
lookup for a match with all the parameters.
std::list< Ipv4EndPoint * >::iterator EndPointsI
Iterator to the container of the IPv4 endpoints.
bool LookupPortLocal(uint16_t port)
Lookup for port local.
void DeAllocate(Ipv4EndPoint *endPoint)
Remove a end point.
A representation of an internet endpoint/connection.
uint16_t GetPeerPort(void)
Get the peer port.
Ipv4Address GetPeerAddress(void)
Get the peer address.
Ptr< NetDevice > GetBoundNetDevice(void)
Returns socket's bound netdevice, if any.
void SetPeer(Ipv4Address address, uint16_t port)
Set the peer information (address and port).
uint16_t GetLocalPort(void)
Get the local port.
bool IsRxEnabled(void)
Checks if the endpoint can receive packets.
Ipv4Address GetLocalAddress(void)
Get the local address.
a class to store IPv4 address information on an interface
Ipv4Mask GetMask(void) const
Get the network mask.
Ipv4Address GetLocal(void) const
Get the local address.
Ipv4InterfaceAddress GetAddress(uint32_t index) const
uint32_t GetNAddresses(void) const
Ptr< NetDevice > GetDevice(void) const
uint16_t GetPrefixLength(void) const
uint16_t port
Definition: dsdv-manet.cc:45
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:265
address
Definition: first.py:44
Every class exported by the ns3 library is enclosed in the ns3 namespace.