A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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  NS_LOG_DEBUG ("Looking at endpoint dport=" << endP->GetLocalPort ()
211  << " daddr=" << endP->GetLocalAddress ()
212  << " sport=" << endP->GetPeerPort ()
213  << " saddr=" << endP->GetPeerAddress ());
214  if (endP->GetLocalPort () != dport)
215  {
216  NS_LOG_LOGIC ("Skipping endpoint " << &endP
217  << " because endpoint dport "
218  << endP->GetLocalPort ()
219  << " does not match packet dport " << dport);
220  continue;
221  }
222  if (endP->GetBoundNetDevice ())
223  {
224  if (endP->GetBoundNetDevice () != incomingInterface->GetDevice ())
225  {
226  NS_LOG_LOGIC ("Skipping endpoint " << &endP
227  << " because endpoint is bound to specific device and"
228  << endP->GetBoundNetDevice ()
229  << " does not match packet device " << incomingInterface->GetDevice ());
230  continue;
231  }
232  }
233  bool subnetDirected = false;
234  Ipv4Address incomingInterfaceAddr = daddr; // may be a broadcast
235  for (uint32_t i = 0; i < incomingInterface->GetNAddresses (); i++)
236  {
237  Ipv4InterfaceAddress addr = incomingInterface->GetAddress (i);
238  if (addr.GetLocal ().CombineMask (addr.GetMask ()) == daddr.CombineMask (addr.GetMask ()) &&
239  daddr.IsSubnetDirectedBroadcast (addr.GetMask ()))
240  {
241  subnetDirected = true;
242  incomingInterfaceAddr = addr.GetLocal ();
243  }
244  }
245  bool isBroadcast = (daddr.IsBroadcast () || subnetDirected == true);
246  NS_LOG_DEBUG ("dest addr " << daddr << " broadcast? " << isBroadcast);
247  bool localAddressMatchesWildCard =
248  endP->GetLocalAddress () == Ipv4Address::GetAny ();
249  bool localAddressMatchesExact = endP->GetLocalAddress () == daddr;
250 
251  if (isBroadcast)
252  {
253  NS_LOG_DEBUG ("Found bcast, localaddr " << endP->GetLocalAddress ());
254  }
255 
256  if (isBroadcast && (endP->GetLocalAddress () != Ipv4Address::GetAny ()))
257  {
258  localAddressMatchesExact = (endP->GetLocalAddress () ==
259  incomingInterfaceAddr);
260  }
261  // if no match here, keep looking
262  if (!(localAddressMatchesExact || localAddressMatchesWildCard))
263  continue;
264  bool remotePeerMatchesExact = endP->GetPeerPort () == sport;
265  bool remotePeerMatchesWildCard = endP->GetPeerPort () == 0;
266  bool remoteAddressMatchesExact = endP->GetPeerAddress () == saddr;
267  bool remoteAddressMatchesWildCard = endP->GetPeerAddress () ==
269  // If remote does not match either with exact or wildcard,
270  // skip this one
271  if (!(remotePeerMatchesExact || remotePeerMatchesWildCard))
272  continue;
273  if (!(remoteAddressMatchesExact || remoteAddressMatchesWildCard))
274  continue;
275 
276  // Now figure out which return list to add this one to
277  if (localAddressMatchesWildCard &&
278  remotePeerMatchesWildCard &&
279  remoteAddressMatchesWildCard)
280  { // Only local port matches exactly
281  retval1.push_back (endP);
282  }
283  if ((localAddressMatchesExact || (isBroadcast && localAddressMatchesWildCard))&&
284  remotePeerMatchesWildCard &&
285  remoteAddressMatchesWildCard)
286  { // Only local port and local address matches exactly
287  retval2.push_back (endP);
288  }
289  if (localAddressMatchesWildCard &&
290  remotePeerMatchesExact &&
291  remoteAddressMatchesExact)
292  { // All but local address
293  retval3.push_back (endP);
294  }
295  if (localAddressMatchesExact &&
296  remotePeerMatchesExact &&
297  remoteAddressMatchesExact)
298  { // All 4 match
299  retval4.push_back (endP);
300  }
301  }
302 
303  // Here we find the most exact match
304  if (!retval4.empty ()) return retval4;
305  if (!retval3.empty ()) return retval3;
306  if (!retval2.empty ()) return retval2;
307  return retval1; // might be empty if no matches
308 }
309 
310 Ipv4EndPoint *
312  uint16_t dport,
313  Ipv4Address saddr,
314  uint16_t sport)
315 {
316  NS_LOG_FUNCTION (this << daddr << dport << saddr << sport);
317 
318  // this code is a copy/paste version of an old BSD ip stack lookup
319  // function.
320  uint32_t genericity = 3;
321  Ipv4EndPoint *generic = 0;
322  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
323  {
324  if ((*i)->GetLocalPort () != dport)
325  {
326  continue;
327  }
328  if ((*i)->GetLocalAddress () == daddr &&
329  (*i)->GetPeerPort () == sport &&
330  (*i)->GetPeerAddress () == saddr)
331  {
332  /* this is an exact match. */
333  return *i;
334  }
335  uint32_t tmp = 0;
336  if ((*i)->GetLocalAddress () == Ipv4Address::GetAny ())
337  {
338  tmp++;
339  }
340  if ((*i)->GetPeerAddress () == Ipv4Address::GetAny ())
341  {
342  tmp++;
343  }
344  if (tmp < genericity)
345  {
346  generic = (*i);
347  genericity = tmp;
348  }
349  }
350  return generic;
351 }
352 uint16_t
354 {
355  // Similar to counting up logic in netinet/in_pcb.c
356  NS_LOG_FUNCTION (this);
357  uint16_t port = m_ephemeral;
358  int count = m_portLast - m_portFirst;
359  do
360  {
361  if (count-- < 0)
362  {
363  return 0;
364  }
365  ++port;
366  if (port < m_portFirst || port > m_portLast)
367  {
368  port = m_portFirst;
369  }
370  } while (LookupPortLocal (port));
371  m_ephemeral = port;
372  return port;
373 }
374 
375 } // namespace ns3
376 
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.
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:170
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:233
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.
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:38
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:203
Ptr< NetDevice > GetDevice(void) const
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:213
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.