A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
ipv4-end-point-demux.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005 INRIA
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7 */
8
10
11#include "ipv4-end-point.h"
13
14#include "ns3/log.h"
15
16namespace ns3
17{
18
19NS_LOG_COMPONENT_DEFINE("Ipv4EndPointDemux");
20
22 : m_ephemeral(49152),
23 m_portLast(65535),
24 m_portFirst(49152)
25{
26 NS_LOG_FUNCTION(this);
27}
28
30{
31 NS_LOG_FUNCTION(this);
32 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
33 {
35 delete endPoint;
36 }
37 m_endPoints.clear();
38}
39
40bool
42{
43 NS_LOG_FUNCTION(this << port);
44 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
45 {
46 if ((*i)->GetLocalPort() == port)
47 {
48 return true;
49 }
50 }
51 return false;
52}
53
54bool
56{
57 NS_LOG_FUNCTION(this << addr << port);
58 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
59 {
60 if ((*i)->GetLocalPort() == port && (*i)->GetLocalAddress() == addr &&
61 (*i)->GetBoundNetDevice() == boundNetDevice)
62 {
63 return true;
64 }
65 }
66 return false;
67}
68
71{
72 NS_LOG_FUNCTION(this);
73 uint16_t port = AllocateEphemeralPort();
74 if (port == 0)
75 {
76 NS_LOG_WARN("Ephemeral port allocation failed.");
77 return nullptr;
78 }
80 m_endPoints.push_back(endPoint);
81 NS_LOG_DEBUG("Now have >>" << m_endPoints.size() << "<< endpoints.");
82 return endPoint;
83}
84
87{
88 NS_LOG_FUNCTION(this << address);
89 uint16_t port = AllocateEphemeralPort();
90 if (port == 0)
91 {
92 NS_LOG_WARN("Ephemeral port allocation failed.");
93 return nullptr;
94 }
95 auto endPoint = new Ipv4EndPoint(address, port);
96 m_endPoints.push_back(endPoint);
97 NS_LOG_DEBUG("Now have >>" << m_endPoints.size() << "<< endpoints.");
98 return endPoint;
99}
100
108
111{
112 NS_LOG_FUNCTION(this << address << port << boundNetDevice);
113 if (LookupLocal(boundNetDevice, address, port) || LookupLocal(nullptr, address, port))
114 {
115 NS_LOG_WARN("Duplicated endpoint.");
116 return nullptr;
117 }
118 auto endPoint = new Ipv4EndPoint(address, port);
119 m_endPoints.push_back(endPoint);
120 NS_LOG_DEBUG("Now have >>" << m_endPoints.size() << "<< endpoints.");
121 return endPoint;
122}
123
126 Ipv4Address localAddress,
127 uint16_t localPort,
129 uint16_t peerPort)
130{
131 NS_LOG_FUNCTION(this << localAddress << localPort << peerAddress << peerPort << boundNetDevice);
132 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
133 {
134 if ((*i)->GetLocalPort() == localPort && (*i)->GetLocalAddress() == localAddress &&
135 (*i)->GetPeerPort() == peerPort && (*i)->GetPeerAddress() == peerAddress &&
136 ((*i)->GetBoundNetDevice() == boundNetDevice || !(*i)->GetBoundNetDevice()))
137 {
138 NS_LOG_WARN("Duplicated endpoint.");
139 return nullptr;
140 }
141 }
142 auto endPoint = new Ipv4EndPoint(localAddress, localPort);
143 endPoint->SetPeer(peerAddress, peerPort);
144 m_endPoints.push_back(endPoint);
145
146 NS_LOG_DEBUG("Now have >>" << m_endPoints.size() << "<< endpoints.");
147
148 return endPoint;
149}
150
151void
153{
154 NS_LOG_FUNCTION(this << endPoint);
155 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
156 {
157 if (*i == endPoint)
158 {
159 delete endPoint;
160 m_endPoints.erase(i);
161 break;
162 }
163 }
164}
165
166/*
167 * return list of all available Endpoints
168 */
171{
172 NS_LOG_FUNCTION(this);
174
175 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
176 {
177 Ipv4EndPoint* endP = *i;
178 ret.push_back(endP);
179 }
180 return ret;
181}
182
183/*
184 * If we have an exact match, we return it.
185 * Otherwise, if we find a generic match, we return it.
186 * Otherwise, we return 0.
187 */
190 uint16_t dport,
192 uint16_t sport,
194{
196
197 EndPoints retval1; // Matches exact on local port, wildcards on others
198 EndPoints retval2; // Matches exact on local port/adder, wildcards on others
199 EndPoints retval3; // Matches all but local address
200 EndPoints retval4; // Exact match on all 4
201
202 NS_LOG_DEBUG("Looking up endpoint for destination address " << daddr << ":" << dport);
203 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
204 {
205 Ipv4EndPoint* endP = *i;
206
207 NS_LOG_DEBUG("Looking at endpoint dport="
208 << endP->GetLocalPort() << " daddr=" << endP->GetLocalAddress()
209 << " sport=" << endP->GetPeerPort() << " saddr=" << endP->GetPeerAddress());
210
211 if (!endP->IsRxEnabled())
212 {
213 NS_LOG_LOGIC("Skipping endpoint " << &endP
214 << " because endpoint can not receive packets");
215 continue;
216 }
217
218 if (endP->GetLocalPort() != dport)
219 {
220 NS_LOG_LOGIC("Skipping endpoint " << &endP << " because endpoint dport "
221 << endP->GetLocalPort()
222 << " does not match packet dport " << dport);
223 continue;
224 }
225 if (endP->GetBoundNetDevice())
226 {
227 if (endP->GetBoundNetDevice() != incomingInterface->GetDevice())
228 {
229 NS_LOG_LOGIC("Skipping endpoint "
230 << &endP << " because endpoint is bound to specific device and"
231 << endP->GetBoundNetDevice() << " does not match packet device "
232 << incomingInterface->GetDevice());
233 continue;
234 }
235 }
236
237 bool localAddressMatchesExact = false;
238 bool localAddressIsAny = false;
239 bool localAddressIsSubnetAny = false;
240
241 // We have 3 cases:
242 // 1) Exact local / destination address match
243 // 2) Local endpoint bound to Any -> matches anything
244 // 3) Local endpoint bound to x.y.z.0 -> matches Subnet-directed broadcast packet (e.g.,
245 // x.y.z.255 in a /24 net) and direct destination match.
246
247 if (endP->GetLocalAddress() == daddr)
248 {
249 // Case 1:
251 }
252 else if (endP->GetLocalAddress() == Ipv4Address::GetAny())
253 {
254 // Case 2:
255 localAddressIsAny = true;
256 }
257 else
258 {
259 // Case 3:
260 for (uint32_t i = 0; i < incomingInterface->GetNAddresses(); i++)
261 {
263
265 if (endP->GetLocalAddress() == addrNetpart)
266 {
267 NS_LOG_LOGIC("Endpoint is SubnetDirectedAny "
268 << endP->GetLocalAddress() << "/"
269 << addr.GetMask().GetPrefixLength());
270
273 {
275 }
276 }
277 }
278
279 // if no match here, keep looking
281 {
282 continue;
283 }
284 }
285
286 bool remotePortMatchesExact = endP->GetPeerPort() == sport;
287 bool remotePortMatchesWildCard = endP->GetPeerPort() == 0;
288 bool remoteAddressMatchesExact = endP->GetPeerAddress() == saddr;
289 bool remoteAddressMatchesWildCard = endP->GetPeerAddress() == Ipv4Address::GetAny();
290
291 // If remote does not match either with exact or wildcard,
292 // skip this one
294 {
295 continue;
296 }
298 {
299 continue;
300 }
301
303
305 { // All 4 match - this is the case of an open TCP connection, for example.
306 NS_LOG_LOGIC("Found an endpoint for case 4, adding " << endP->GetLocalAddress() << ":"
307 << endP->GetLocalPort());
308 retval4.push_back(endP);
309 }
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() << ":"
313 << endP->GetLocalPort());
314 retval3.push_back(endP);
315 }
317 { // Only local port and local address matches exactly - Not yet opened connection
318 NS_LOG_LOGIC("Found an endpoint for case 2, adding " << endP->GetLocalAddress() << ":"
319 << endP->GetLocalPort());
320 retval2.push_back(endP);
321 }
324 { // Only local port matches exactly - Endpoint open to "any" connection
325 NS_LOG_LOGIC("Found an endpoint for case 1, adding " << endP->GetLocalAddress() << ":"
326 << endP->GetLocalPort());
327 retval1.push_back(endP);
328 }
329 }
330
331 // Here we find the most exact match
333 if (!retval4.empty())
334 {
335 retval = retval4;
336 }
337 else if (!retval3.empty())
338 {
339 retval = retval3;
340 }
341 else if (!retval2.empty())
342 {
343 retval = retval2;
344 }
345 else
346 {
347 retval = retval1;
348 }
349
350 NS_ABORT_MSG_IF(retval.size() > 1,
351 "Too many endpoints - perhaps you created too many sockets without binding "
352 "them to different NetDevices.");
353 return retval; // might be empty if no matches
354}
355
358 uint16_t dport,
360 uint16_t sport)
361{
362 NS_LOG_FUNCTION(this << daddr << dport << saddr << sport);
363
364 // this code is a copy/paste version of an old BSD ip stack lookup
365 // function.
367 Ipv4EndPoint* generic = nullptr;
368 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
369 {
370 if ((*i)->GetLocalPort() != dport)
371 {
372 continue;
373 }
374 if ((*i)->GetLocalAddress() == daddr && (*i)->GetPeerPort() == sport &&
375 (*i)->GetPeerAddress() == saddr)
376 {
377 /* this is an exact match. */
378 return *i;
379 }
380 uint32_t tmp = 0;
381 if ((*i)->GetLocalAddress() == Ipv4Address::GetAny())
382 {
383 tmp++;
384 }
385 if ((*i)->GetPeerAddress() == Ipv4Address::GetAny())
386 {
387 tmp++;
388 }
389 if (tmp < genericity)
390 {
391 generic = (*i);
392 genericity = tmp;
393 }
394 }
395 return generic;
396}
397
398uint16_t
400{
401 // Similar to counting up logic in netinet/in_pcb.c
402 NS_LOG_FUNCTION(this);
403 uint16_t port = m_ephemeral;
404 int count = m_portLast - m_portFirst;
405 do
406 {
407 if (count-- < 0)
408 {
409 return 0;
410 }
411 ++port;
413 {
415 }
416 } while (LookupPortLocal(port));
418 return port;
419}
420
421} // namespace ns3
Ipv4 addresses are stored in host order in this class.
Ipv4Address CombineMask(const Ipv4Mask &mask) const
Combine this address with a network mask.
static Ipv4Address GetAny()
uint16_t m_portFirst
The first ephemeral port.
uint16_t AllocateEphemeralPort()
Allocate an ephemeral port.
EndPoints m_endPoints
A list of IPv4 end points.
uint16_t m_portLast
The last ephemeral port.
Ipv4EndPoint * SimpleLookup(Ipv4Address daddr, uint16_t dport, Ipv4Address saddr, uint16_t sport)
simple lookup for a match with all the parameters.
bool LookupLocal(Ptr< NetDevice > boundNetDevice, Ipv4Address addr, uint16_t port)
Lookup for address and port.
EndPoints GetAllEndPoints()
Get the entire list of end points registered.
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.
Ipv4EndPoint * Allocate()
Allocate a Ipv4EndPoint.
std::list< Ipv4EndPoint * > EndPoints
Container of the IPv4 endpoints.
A representation of an internet endpoint/connection.
a class to store IPv4 address information on an interface
Ipv4Mask GetMask() const
Get the network mask.
Ipv4Address GetAddress() const
Get the local address.
Ipv4Address GetLocal() const
Get the local address.
uint16_t GetPrefixLength() const
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:66
uint16_t port
Definition dsdv-manet.cc:33
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#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:250
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Every class exported by the ns3 library is enclosed in the ns3 namespace.