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
22#include "ipv4-end-point.h"
24#include "ns3/log.h"
25
26
27namespace ns3 {
28
29NS_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
48bool
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
62bool
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 }
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
112{
113 NS_LOG_FUNCTION (this << port << boundNetDevice);
114
115 return Allocate (boundNetDevice, Ipv4Address::GetAny (), port);
116}
117
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
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
160void
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 */
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
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}
380uint16_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 {
397 }
398 } while (LookupPortLocal (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.
std::list< Ipv4EndPoint * >::iterator EndPointsI
Iterator to the container of the IPv4 endpoints.
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.
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.