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 {
34 Ipv4EndPoint* endPoint = *i;
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 }
79 auto endPoint = new Ipv4EndPoint(Ipv4Address::GetAny(), port);
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
103{
104 NS_LOG_FUNCTION(this << port << boundNetDevice);
105
106 return Allocate(boundNetDevice, Ipv4Address::GetAny(), port);
107}
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,
128 Ipv4Address peerAddress,
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);
173 EndPoints ret;
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,
191 Ipv4Address saddr,
192 uint16_t sport,
193 Ptr<Ipv4Interface> incomingInterface)
194{
195 NS_LOG_FUNCTION(this << daddr << dport << saddr << sport << incomingInterface);
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:
250 localAddressMatchesExact = true;
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 {
262 Ipv4InterfaceAddress addr = incomingInterface->GetAddress(i);
263
264 Ipv4Address addrNetpart = addr.GetLocal().CombineMask(addr.GetMask());
265 if (endP->GetLocalAddress() == addrNetpart)
266 {
267 NS_LOG_LOGIC("Endpoint is SubnetDirectedAny "
268 << endP->GetLocalAddress() << "/"
269 << addr.GetMask().GetPrefixLength());
270
271 Ipv4Address daddrNetPart = daddr.CombineMask(addr.GetMask());
272 if (addrNetpart == daddrNetPart)
273 {
274 localAddressIsSubnetAny = true;
275 }
276 }
277 }
278
279 // if no match here, keep looking
280 if (!localAddressIsSubnetAny)
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
293 if (!(remotePortMatchesExact || remotePortMatchesWildCard))
294 {
295 continue;
296 }
297 if (!(remoteAddressMatchesExact || remoteAddressMatchesWildCard))
298 {
299 continue;
300 }
301
302 bool localAddressMatchesWildCard = localAddressIsAny || localAddressIsSubnetAny;
303
304 if (localAddressMatchesExact && remoteAddressMatchesExact && remotePortMatchesExact)
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 }
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() << ":"
313 << endP->GetLocalPort());
314 retval3.push_back(endP);
315 }
316 if (localAddressMatchesExact && remoteAddressMatchesWildCard && remotePortMatchesWildCard)
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 }
322 if (localAddressMatchesWildCard && remoteAddressMatchesWildCard &&
323 remotePortMatchesWildCard)
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
332 EndPoints retval;
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,
359 Ipv4Address saddr,
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.
366 uint32_t genericity = 3;
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.
Ipv4Address GetLocalAddress() const
Get the local address.
uint16_t GetPeerPort() const
Get the peer port.
Ptr< NetDevice > GetBoundNetDevice() const
Returns socket's bound netdevice, if any.
uint16_t GetLocalPort() const
Get the local port.
bool IsRxEnabled() const
Checks if the endpoint can receive packets.
Ipv4Address GetPeerAddress() const
Get the peer address.
a class to store IPv4 address information on an interface
Ipv4Mask GetMask() const
Get the network mask.
Ipv4Address GetLocal() const
Get the local address.
uint16_t GetPrefixLength() const
Smart pointer class similar to boost::intrusive_ptr.
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
Every class exported by the ns3 library is enclosed in the ns3 namespace.