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 "ns3/log.h"
24 
25 namespace ns3 {
26 
27 NS_LOG_COMPONENT_DEFINE ("Ipv4EndPointDemux");
28 
30  : m_ephemeral (49152), m_portLast (65535), m_portFirst (49152)
31 {
32  NS_LOG_FUNCTION (this);
33 }
34 
36 {
37  NS_LOG_FUNCTION (this);
38  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
39  {
40  Ipv4EndPoint *endPoint = *i;
41  delete endPoint;
42  }
43  m_endPoints.clear ();
44 }
45 
46 bool
48 {
49  NS_LOG_FUNCTION (this << port);
50  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
51  {
52  if ((*i)->GetLocalPort () == port)
53  {
54  return true;
55  }
56  }
57  return false;
58 }
59 
60 bool
62 {
63  NS_LOG_FUNCTION (this << addr << port);
64  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
65  {
66  if ((*i)->GetLocalPort () == port &&
67  (*i)->GetLocalAddress () == addr)
68  {
69  return true;
70  }
71  }
72  return false;
73 }
74 
77 {
78  NS_LOG_FUNCTION (this);
79  uint16_t port = AllocateEphemeralPort ();
80  if (port == 0)
81  {
82  NS_LOG_WARN ("Ephemeral port allocation failed.");
83  return 0;
84  }
85  Ipv4EndPoint *endPoint = new Ipv4EndPoint (Ipv4Address::GetAny (), port);
86  m_endPoints.push_back (endPoint);
87  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
88  return endPoint;
89 }
90 
93 {
94  NS_LOG_FUNCTION (this << address);
95  uint16_t port = AllocateEphemeralPort ();
96  if (port == 0)
97  {
98  NS_LOG_WARN ("Ephemeral port allocation failed.");
99  return 0;
100  }
101  Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port);
102  m_endPoints.push_back (endPoint);
103  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
104  return endPoint;
105 }
106 
107 Ipv4EndPoint *
109 {
110  NS_LOG_FUNCTION (this << port);
111 
112  return Allocate (Ipv4Address::GetAny (), port);
113 }
114 
115 Ipv4EndPoint *
117 {
118  NS_LOG_FUNCTION (this << address << port);
119  if (LookupLocal (address, port))
120  {
121  NS_LOG_WARN ("Duplicate address/port; failing.");
122  return 0;
123  }
124  Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port);
125  m_endPoints.push_back (endPoint);
126  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
127  return endPoint;
128 }
129 
130 Ipv4EndPoint *
131 Ipv4EndPointDemux::Allocate (Ipv4Address localAddress, uint16_t localPort,
132  Ipv4Address peerAddress, uint16_t peerPort)
133 {
134  NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
135  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
136  {
137  if ((*i)->GetLocalPort () == localPort &&
138  (*i)->GetLocalAddress () == localAddress &&
139  (*i)->GetPeerPort () == peerPort &&
140  (*i)->GetPeerAddress () == peerAddress)
141  {
142  NS_LOG_WARN ("No way we can allocate this end-point.");
143  /* no way we can allocate this end-point. */
144  return 0;
145  }
146  }
147  Ipv4EndPoint *endPoint = new Ipv4EndPoint (localAddress, localPort);
148  endPoint->SetPeer (peerAddress, peerPort);
149  m_endPoints.push_back (endPoint);
150 
151  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
152 
153  return endPoint;
154 }
155 
156 void
158 {
159  NS_LOG_FUNCTION (this << endPoint);
160  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
161  {
162  if (*i == endPoint)
163  {
164  delete endPoint;
165  m_endPoints.erase (i);
166  break;
167  }
168  }
169 }
170 
171 /*
172  * return list of all available Endpoints
173  */
176 {
177  NS_LOG_FUNCTION (this);
178  EndPoints ret;
179 
180  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
181  {
182  Ipv4EndPoint* endP = *i;
183  ret.push_back (endP);
184  }
185  return ret;
186 }
187 
188 
189 /*
190  * If we have an exact match, we return it.
191  * Otherwise, if we find a generic match, we return it.
192  * Otherwise, we return 0.
193  */
195 Ipv4EndPointDemux::Lookup (Ipv4Address daddr, uint16_t dport,
196  Ipv4Address saddr, uint16_t sport,
197  Ptr<Ipv4Interface> incomingInterface)
198 {
199  NS_LOG_FUNCTION (this << daddr << dport << saddr << sport << incomingInterface);
200 
201  EndPoints retval1; // Matches exact on local port, wildcards on others
202  EndPoints retval2; // Matches exact on local port/adder, wildcards on others
203  EndPoints retval3; // Matches all but local address
204  EndPoints retval4; // Exact match on all 4
205 
206  NS_LOG_DEBUG ("Looking up endpoint for destination address " << daddr);
207  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
208  {
209  Ipv4EndPoint* endP = *i;
210 
211  NS_LOG_DEBUG ("Looking at endpoint dport=" << endP->GetLocalPort ()
212  << " daddr=" << endP->GetLocalAddress ()
213  << " sport=" << endP->GetPeerPort ()
214  << " saddr=" << endP->GetPeerAddress ());
215 
216  if (!endP->IsRxEnabled ())
217  {
218  NS_LOG_LOGIC ("Skipping endpoint " << &endP
219  << " because endpoint can not receive packets");
220  continue;
221  }
222 
223  if (endP->GetLocalPort () != dport)
224  {
225  NS_LOG_LOGIC ("Skipping endpoint " << &endP
226  << " because endpoint dport "
227  << endP->GetLocalPort ()
228  << " does not match packet dport " << dport);
229  continue;
230  }
231  if (endP->GetBoundNetDevice ())
232  {
233  if (endP->GetBoundNetDevice () != incomingInterface->GetDevice ())
234  {
235  NS_LOG_LOGIC ("Skipping endpoint " << &endP
236  << " because endpoint is bound to specific device and"
237  << endP->GetBoundNetDevice ()
238  << " does not match packet device " << incomingInterface->GetDevice ());
239  continue;
240  }
241  }
242  bool subnetDirected = false;
243  Ipv4Address incomingInterfaceAddr = daddr; // may be a broadcast
244  for (uint32_t i = 0; i < incomingInterface->GetNAddresses (); i++)
245  {
246  Ipv4InterfaceAddress addr = incomingInterface->GetAddress (i);
247  if (addr.GetLocal ().CombineMask (addr.GetMask ()) == daddr.CombineMask (addr.GetMask ()) &&
248  daddr.IsSubnetDirectedBroadcast (addr.GetMask ()))
249  {
250  subnetDirected = true;
251  incomingInterfaceAddr = addr.GetLocal ();
252  }
253  }
254  bool isBroadcast = (daddr.IsBroadcast () || subnetDirected == true);
255  NS_LOG_DEBUG ("dest addr " << daddr << " broadcast? " << isBroadcast);
256  bool localAddressMatchesWildCard =
257  endP->GetLocalAddress () == Ipv4Address::GetAny ();
258  bool localAddressMatchesExact = endP->GetLocalAddress () == daddr;
259 
260  if (isBroadcast)
261  {
262  NS_LOG_DEBUG ("Found bcast, localaddr " << endP->GetLocalAddress ());
263  }
264 
265  if (isBroadcast && (endP->GetLocalAddress () != Ipv4Address::GetAny ()))
266  {
267  localAddressMatchesExact = (endP->GetLocalAddress () ==
268  incomingInterfaceAddr);
269  }
270  // if no match here, keep looking
271  if (!(localAddressMatchesExact || localAddressMatchesWildCard))
272  continue;
273  bool remotePeerMatchesExact = endP->GetPeerPort () == sport;
274  bool remotePeerMatchesWildCard = endP->GetPeerPort () == 0;
275  bool remoteAddressMatchesExact = endP->GetPeerAddress () == saddr;
276  bool remoteAddressMatchesWildCard = endP->GetPeerAddress () ==
278  // If remote does not match either with exact or wildcard,
279  // skip this one
280  if (!(remotePeerMatchesExact || remotePeerMatchesWildCard))
281  continue;
282  if (!(remoteAddressMatchesExact || remoteAddressMatchesWildCard))
283  continue;
284 
285  // Now figure out which return list to add this one to
286  if (localAddressMatchesWildCard &&
287  remotePeerMatchesWildCard &&
288  remoteAddressMatchesWildCard)
289  { // Only local port matches exactly
290  retval1.push_back (endP);
291  }
292  if ((localAddressMatchesExact || (isBroadcast && localAddressMatchesWildCard))&&
293  remotePeerMatchesWildCard &&
294  remoteAddressMatchesWildCard)
295  { // Only local port and local address matches exactly
296  retval2.push_back (endP);
297  }
298  if (localAddressMatchesWildCard &&
299  remotePeerMatchesExact &&
300  remoteAddressMatchesExact)
301  { // All but local address
302  retval3.push_back (endP);
303  }
304  if (localAddressMatchesExact &&
305  remotePeerMatchesExact &&
306  remoteAddressMatchesExact)
307  { // All 4 match
308  retval4.push_back (endP);
309  }
310  }
311 
312  // Here we find the most exact match
313  if (!retval4.empty ()) return retval4;
314  if (!retval3.empty ()) return retval3;
315  if (!retval2.empty ()) return retval2;
316  return retval1; // might be empty if no matches
317 }
318 
319 Ipv4EndPoint *
321  uint16_t dport,
322  Ipv4Address saddr,
323  uint16_t sport)
324 {
325  NS_LOG_FUNCTION (this << daddr << dport << saddr << sport);
326 
327  // this code is a copy/paste version of an old BSD ip stack lookup
328  // function.
329  uint32_t genericity = 3;
330  Ipv4EndPoint *generic = 0;
331  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
332  {
333  if ((*i)->GetLocalPort () != dport)
334  {
335  continue;
336  }
337  if ((*i)->GetLocalAddress () == daddr &&
338  (*i)->GetPeerPort () == sport &&
339  (*i)->GetPeerAddress () == saddr)
340  {
341  /* this is an exact match. */
342  return *i;
343  }
344  uint32_t tmp = 0;
345  if ((*i)->GetLocalAddress () == Ipv4Address::GetAny ())
346  {
347  tmp++;
348  }
349  if ((*i)->GetPeerAddress () == Ipv4Address::GetAny ())
350  {
351  tmp++;
352  }
353  if (tmp < genericity)
354  {
355  generic = (*i);
356  genericity = tmp;
357  }
358  }
359  return generic;
360 }
361 uint16_t
363 {
364  // Similar to counting up logic in netinet/in_pcb.c
365  NS_LOG_FUNCTION (this);
366  uint16_t port = m_ephemeral;
367  int count = m_portLast - m_portFirst;
368  do
369  {
370  if (count-- < 0)
371  {
372  return 0;
373  }
374  ++port;
375  if (port < m_portFirst || port > m_portLast)
376  {
377  port = m_portFirst;
378  }
379  } while (LookupPortLocal (port));
380  m_ephemeral = port;
381  return port;
382 }
383 
384 } // namespace ns3
385 
static Ipv4Address GetAny(void)
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
Ipv4Mask GetMask(void) const
Get the network mask.
Ipv4Address GetLocal(void) const
Get the local address.
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:201
uint16_t m_ephemeral
The ephemeral port.
bool LookupPortLocal(uint16_t port)
Lookup for port local.
Ipv4Address CombineMask(Ipv4Mask const &mask) const
Combine this address with a network mask.
uint16_t m_portFirst
The first ephemeral port.
uint16_t port
Definition: dsdv-manet.cc:44
bool IsSubnetDirectedBroadcast(Ipv4Mask const &mask) const
Generate subnet-directed broadcast address corresponding to mask.
Ipv4Address GetLocalAddress(void)
Get the local address.
bool IsBroadcast(void) const
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:252
uint16_t m_portLast
The last ephemeral port.
Ipv4InterfaceAddress GetAddress(uint32_t index) const
Ptr< NetDevice > GetBoundNetDevice(void)
Returns socket's bound netdevice, if any.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ipv4EndPoint * SimpleLookup(Ipv4Address daddr, uint16_t dport, Ipv4Address saddr, uint16_t sport)
simple lookup for a match with all the parameters.
bool LookupLocal(Ipv4Address addr, uint16_t port)
Lookup for address and port.
void SetPeer(Ipv4Address address, uint16_t port)
Set the peer informations (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:40
std::list< Ipv4EndPoint * > EndPoints
Container of the IPv4 endpoints.
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:228
Ptr< NetDevice > GetDevice(void) const
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:236
Ipv4Address GetPeerAddress(void)
Get the peer address.
uint16_t GetPeerPort(void)
Get the peer port.
std::list< Ipv4EndPoint * >::iterator EndPointsI
Iterator to the container of the IPv4 endpoints.
tuple address
Definition: first.py:37
void DeAllocate(Ipv4EndPoint *endPoint)
Remove a end point.
EndPoints m_endPoints
A list of IPv4 end points.
uint32_t GetNAddresses(void) const
uint16_t AllocateEphemeralPort(void)
Allocate an ephemeral port.
A representation of an internet endpoint/connection.
Ipv4EndPoint * Allocate(void)
Allocate a Ipv4EndPoint.