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  {
71  return true;
72  }
73  }
74  return false;
75 }
76 
79 {
80  NS_LOG_FUNCTION (this);
81  uint16_t port = AllocateEphemeralPort ();
82  if (port == 0)
83  {
84  NS_LOG_WARN ("Ephemeral port allocation failed.");
85  return 0;
86  }
87  Ipv4EndPoint *endPoint = new Ipv4EndPoint (Ipv4Address::GetAny (), port);
88  m_endPoints.push_back (endPoint);
89  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
90  return endPoint;
91 }
92 
95 {
96  NS_LOG_FUNCTION (this << address);
97  uint16_t port = AllocateEphemeralPort ();
98  if (port == 0)
99  {
100  NS_LOG_WARN ("Ephemeral port allocation failed.");
101  return 0;
102  }
103  Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port);
104  m_endPoints.push_back (endPoint);
105  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
106  return endPoint;
107 }
108 
109 Ipv4EndPoint *
111 {
112  NS_LOG_FUNCTION (this << port);
113 
114  return Allocate (Ipv4Address::GetAny (), port);
115 }
116 
117 Ipv4EndPoint *
119 {
120  NS_LOG_FUNCTION (this << address << port);
121  if (LookupLocal (address, port))
122  {
123  NS_LOG_WARN ("Duplicate address/port; failing.");
124  return 0;
125  }
126  Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port);
127  m_endPoints.push_back (endPoint);
128  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
129  return endPoint;
130 }
131 
132 Ipv4EndPoint *
133 Ipv4EndPointDemux::Allocate (Ipv4Address localAddress, uint16_t localPort,
134  Ipv4Address peerAddress, uint16_t peerPort)
135 {
136  NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
137  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
138  {
139  if ((*i)->GetLocalPort () == localPort &&
140  (*i)->GetLocalAddress () == localAddress &&
141  (*i)->GetPeerPort () == peerPort &&
142  (*i)->GetPeerAddress () == peerAddress)
143  {
144  NS_LOG_WARN ("No way we can allocate this end-point.");
145  /* no way we can allocate this end-point. */
146  return 0;
147  }
148  }
149  Ipv4EndPoint *endPoint = new Ipv4EndPoint (localAddress, localPort);
150  endPoint->SetPeer (peerAddress, peerPort);
151  m_endPoints.push_back (endPoint);
152 
153  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
154 
155  return endPoint;
156 }
157 
158 void
160 {
161  NS_LOG_FUNCTION (this << endPoint);
162  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
163  {
164  if (*i == endPoint)
165  {
166  delete endPoint;
167  m_endPoints.erase (i);
168  break;
169  }
170  }
171 }
172 
173 /*
174  * return list of all available Endpoints
175  */
178 {
179  NS_LOG_FUNCTION (this);
180  EndPoints ret;
181 
182  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
183  {
184  Ipv4EndPoint* endP = *i;
185  ret.push_back (endP);
186  }
187  return ret;
188 }
189 
190 
191 /*
192  * If we have an exact match, we return it.
193  * Otherwise, if we find a generic match, we return it.
194  * Otherwise, we return 0.
195  */
197 Ipv4EndPointDemux::Lookup (Ipv4Address daddr, uint16_t dport,
198  Ipv4Address saddr, uint16_t sport,
199  Ptr<Ipv4Interface> incomingInterface)
200 {
201  NS_LOG_FUNCTION (this << daddr << dport << saddr << sport << incomingInterface);
202 
203  EndPoints retval1; // Matches exact on local port, wildcards on others
204  EndPoints retval2; // Matches exact on local port/adder, wildcards on others
205  EndPoints retval3; // Matches all but local address
206  EndPoints retval4; // Exact match on all 4
207 
208  NS_LOG_DEBUG ("Looking up endpoint for destination address " << daddr);
209  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
210  {
211  Ipv4EndPoint* endP = *i;
212 
213  NS_LOG_DEBUG ("Looking at endpoint dport=" << endP->GetLocalPort ()
214  << " daddr=" << endP->GetLocalAddress ()
215  << " sport=" << endP->GetPeerPort ()
216  << " saddr=" << endP->GetPeerAddress ());
217 
218  if (!endP->IsRxEnabled ())
219  {
220  NS_LOG_LOGIC ("Skipping endpoint " << &endP
221  << " because endpoint can not receive packets");
222  continue;
223  }
224 
225  if (endP->GetLocalPort () != dport)
226  {
227  NS_LOG_LOGIC ("Skipping endpoint " << &endP
228  << " because endpoint dport "
229  << endP->GetLocalPort ()
230  << " does not match packet dport " << dport);
231  continue;
232  }
233  if (endP->GetBoundNetDevice ())
234  {
235  if (endP->GetBoundNetDevice () != incomingInterface->GetDevice ())
236  {
237  NS_LOG_LOGIC ("Skipping endpoint " << &endP
238  << " because endpoint is bound to specific device and"
239  << endP->GetBoundNetDevice ()
240  << " does not match packet device " << incomingInterface->GetDevice ());
241  continue;
242  }
243  }
244  bool subnetDirected = false;
245  Ipv4Address incomingInterfaceAddr = daddr; // may be a broadcast
246  for (uint32_t i = 0; i < incomingInterface->GetNAddresses (); i++)
247  {
248  Ipv4InterfaceAddress addr = incomingInterface->GetAddress (i);
249  if (addr.GetLocal ().CombineMask (addr.GetMask ()) == daddr.CombineMask (addr.GetMask ()) &&
250  daddr.IsSubnetDirectedBroadcast (addr.GetMask ()))
251  {
252  subnetDirected = true;
253  incomingInterfaceAddr = addr.GetLocal ();
254  }
255  }
256  bool isBroadcast = (daddr.IsBroadcast () || subnetDirected == true);
257  NS_LOG_DEBUG ("dest addr " << daddr << " broadcast? " << isBroadcast);
258  bool localAddressMatchesWildCard =
259  endP->GetLocalAddress () == Ipv4Address::GetAny ();
260  bool localAddressMatchesExact = endP->GetLocalAddress () == daddr;
261 
262  if (isBroadcast)
263  {
264  NS_LOG_DEBUG ("Found bcast, localaddr " << endP->GetLocalAddress ());
265  }
266 
267  if (isBroadcast && (endP->GetLocalAddress () != Ipv4Address::GetAny ()))
268  {
269  localAddressMatchesExact = (endP->GetLocalAddress () ==
270  incomingInterfaceAddr);
271  }
272  // if no match here, keep looking
273  if (!(localAddressMatchesExact || localAddressMatchesWildCard))
274  continue;
275  bool remotePeerMatchesExact = endP->GetPeerPort () == sport;
276  bool remotePeerMatchesWildCard = endP->GetPeerPort () == 0;
277  bool remoteAddressMatchesExact = endP->GetPeerAddress () == saddr;
278  bool remoteAddressMatchesWildCard = endP->GetPeerAddress () ==
280  // If remote does not match either with exact or wildcard,
281  // skip this one
282  if (!(remotePeerMatchesExact || remotePeerMatchesWildCard))
283  continue;
284  if (!(remoteAddressMatchesExact || remoteAddressMatchesWildCard))
285  continue;
286 
287  // Now figure out which return list to add this one to
288  if (localAddressMatchesWildCard &&
289  remotePeerMatchesWildCard &&
290  remoteAddressMatchesWildCard)
291  { // Only local port matches exactly
292  retval1.push_back (endP);
293  }
294  if ((localAddressMatchesExact || (isBroadcast && localAddressMatchesWildCard))&&
295  remotePeerMatchesWildCard &&
296  remoteAddressMatchesWildCard)
297  { // Only local port and local address matches exactly
298  retval2.push_back (endP);
299  }
300  if (localAddressMatchesWildCard &&
301  remotePeerMatchesExact &&
302  remoteAddressMatchesExact)
303  { // All but local address
304  retval3.push_back (endP);
305  }
306  if (localAddressMatchesExact &&
307  remotePeerMatchesExact &&
308  remoteAddressMatchesExact)
309  { // All 4 match
310  retval4.push_back (endP);
311  }
312  }
313 
314  // Here we find the most exact match
315  if (!retval4.empty ()) return retval4;
316  if (!retval3.empty ()) return retval3;
317  if (!retval2.empty ()) return retval2;
318  return retval1; // might be empty if no matches
319 }
320 
321 Ipv4EndPoint *
323  uint16_t dport,
324  Ipv4Address saddr,
325  uint16_t sport)
326 {
327  NS_LOG_FUNCTION (this << daddr << dport << saddr << sport);
328 
329  // this code is a copy/paste version of an old BSD ip stack lookup
330  // function.
331  uint32_t genericity = 3;
332  Ipv4EndPoint *generic = 0;
333  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
334  {
335  if ((*i)->GetLocalPort () != dport)
336  {
337  continue;
338  }
339  if ((*i)->GetLocalAddress () == daddr &&
340  (*i)->GetPeerPort () == sport &&
341  (*i)->GetPeerAddress () == saddr)
342  {
343  /* this is an exact match. */
344  return *i;
345  }
346  uint32_t tmp = 0;
347  if ((*i)->GetLocalAddress () == Ipv4Address::GetAny ())
348  {
349  tmp++;
350  }
351  if ((*i)->GetPeerAddress () == Ipv4Address::GetAny ())
352  {
353  tmp++;
354  }
355  if (tmp < genericity)
356  {
357  generic = (*i);
358  genericity = tmp;
359  }
360  }
361  return generic;
362 }
363 uint16_t
365 {
366  // Similar to counting up logic in netinet/in_pcb.c
367  NS_LOG_FUNCTION (this);
368  uint16_t port = m_ephemeral;
369  int count = m_portLast - m_portFirst;
370  do
371  {
372  if (count-- < 0)
373  {
374  return 0;
375  }
376  ++port;
377  if (port < m_portFirst || port > m_portLast)
378  {
379  port = m_portFirst;
380  }
381  } while (LookupPortLocal (port));
382  m_ephemeral = port;
383  return port;
384 }
385 
386 } // namespace ns3
387 
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.