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 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18 */
19
21
22#include "ipv4-end-point.h"
24
25#include "ns3/log.h"
26
27namespace ns3
28{
29
30NS_LOG_COMPONENT_DEFINE("Ipv4EndPointDemux");
31
33 : m_ephemeral(49152),
34 m_portLast(65535),
35 m_portFirst(49152)
36{
37 NS_LOG_FUNCTION(this);
38}
39
41{
42 NS_LOG_FUNCTION(this);
43 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
44 {
45 Ipv4EndPoint* endPoint = *i;
46 delete endPoint;
47 }
48 m_endPoints.clear();
49}
50
51bool
53{
54 NS_LOG_FUNCTION(this << port);
55 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
56 {
57 if ((*i)->GetLocalPort() == port)
58 {
59 return true;
60 }
61 }
62 return false;
63}
64
65bool
67{
68 NS_LOG_FUNCTION(this << addr << port);
69 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
70 {
71 if ((*i)->GetLocalPort() == port && (*i)->GetLocalAddress() == addr &&
72 (*i)->GetBoundNetDevice() == boundNetDevice)
73 {
74 return true;
75 }
76 }
77 return false;
78}
79
82{
83 NS_LOG_FUNCTION(this);
84 uint16_t port = AllocateEphemeralPort();
85 if (port == 0)
86 {
87 NS_LOG_WARN("Ephemeral port allocation failed.");
88 return nullptr;
89 }
90 auto endPoint = new Ipv4EndPoint(Ipv4Address::GetAny(), port);
91 m_endPoints.push_back(endPoint);
92 NS_LOG_DEBUG("Now have >>" << m_endPoints.size() << "<< endpoints.");
93 return endPoint;
94}
95
98{
99 NS_LOG_FUNCTION(this << address);
100 uint16_t port = AllocateEphemeralPort();
101 if (port == 0)
102 {
103 NS_LOG_WARN("Ephemeral port allocation failed.");
104 return nullptr;
105 }
106 auto endPoint = new Ipv4EndPoint(address, port);
107 m_endPoints.push_back(endPoint);
108 NS_LOG_DEBUG("Now have >>" << m_endPoints.size() << "<< endpoints.");
109 return endPoint;
110}
111
114{
115 NS_LOG_FUNCTION(this << port << boundNetDevice);
116
117 return Allocate(boundNetDevice, Ipv4Address::GetAny(), port);
118}
119
122{
123 NS_LOG_FUNCTION(this << address << port << boundNetDevice);
124 if (LookupLocal(boundNetDevice, address, port) || LookupLocal(nullptr, address, port))
125 {
126 NS_LOG_WARN("Duplicated endpoint.");
127 return nullptr;
128 }
129 auto endPoint = new Ipv4EndPoint(address, port);
130 m_endPoints.push_back(endPoint);
131 NS_LOG_DEBUG("Now have >>" << m_endPoints.size() << "<< endpoints.");
132 return endPoint;
133}
134
137 Ipv4Address localAddress,
138 uint16_t localPort,
139 Ipv4Address peerAddress,
140 uint16_t peerPort)
141{
142 NS_LOG_FUNCTION(this << localAddress << localPort << peerAddress << peerPort << boundNetDevice);
143 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
144 {
145 if ((*i)->GetLocalPort() == localPort && (*i)->GetLocalAddress() == localAddress &&
146 (*i)->GetPeerPort() == peerPort && (*i)->GetPeerAddress() == peerAddress &&
147 ((*i)->GetBoundNetDevice() == boundNetDevice || !(*i)->GetBoundNetDevice()))
148 {
149 NS_LOG_WARN("Duplicated endpoint.");
150 return nullptr;
151 }
152 }
153 auto endPoint = new Ipv4EndPoint(localAddress, localPort);
154 endPoint->SetPeer(peerAddress, peerPort);
155 m_endPoints.push_back(endPoint);
156
157 NS_LOG_DEBUG("Now have >>" << m_endPoints.size() << "<< endpoints.");
158
159 return endPoint;
160}
161
162void
164{
165 NS_LOG_FUNCTION(this << endPoint);
166 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
167 {
168 if (*i == endPoint)
169 {
170 delete endPoint;
171 m_endPoints.erase(i);
172 break;
173 }
174 }
175}
176
177/*
178 * return list of all available Endpoints
179 */
182{
183 NS_LOG_FUNCTION(this);
184 EndPoints ret;
185
186 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
187 {
188 Ipv4EndPoint* endP = *i;
189 ret.push_back(endP);
190 }
191 return ret;
192}
193
194/*
195 * If we have an exact match, we return it.
196 * Otherwise, if we find a generic match, we return it.
197 * Otherwise, we return 0.
198 */
201 uint16_t dport,
202 Ipv4Address saddr,
203 uint16_t sport,
204 Ptr<Ipv4Interface> incomingInterface)
205{
206 NS_LOG_FUNCTION(this << daddr << dport << saddr << sport << incomingInterface);
207
208 EndPoints retval1; // Matches exact on local port, wildcards on others
209 EndPoints retval2; // Matches exact on local port/adder, wildcards on others
210 EndPoints retval3; // Matches all but local address
211 EndPoints retval4; // Exact match on all 4
212
213 NS_LOG_DEBUG("Looking up endpoint for destination address " << daddr << ":" << dport);
214 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
215 {
216 Ipv4EndPoint* endP = *i;
217
218 NS_LOG_DEBUG("Looking at endpoint dport="
219 << endP->GetLocalPort() << " daddr=" << endP->GetLocalAddress()
220 << " sport=" << endP->GetPeerPort() << " saddr=" << endP->GetPeerAddress());
221
222 if (!endP->IsRxEnabled())
223 {
224 NS_LOG_LOGIC("Skipping endpoint " << &endP
225 << " because endpoint can not receive packets");
226 continue;
227 }
228
229 if (endP->GetLocalPort() != dport)
230 {
231 NS_LOG_LOGIC("Skipping endpoint " << &endP << " because endpoint dport "
232 << endP->GetLocalPort()
233 << " does not match packet dport " << dport);
234 continue;
235 }
236 if (endP->GetBoundNetDevice())
237 {
238 if (endP->GetBoundNetDevice() != incomingInterface->GetDevice())
239 {
240 NS_LOG_LOGIC("Skipping endpoint "
241 << &endP << " because endpoint is bound to specific device and"
242 << endP->GetBoundNetDevice() << " does not match packet device "
243 << incomingInterface->GetDevice());
244 continue;
245 }
246 }
247
248 bool localAddressMatchesExact = false;
249 bool localAddressIsAny = false;
250 bool localAddressIsSubnetAny = false;
251
252 // We have 3 cases:
253 // 1) Exact local / destination address match
254 // 2) Local endpoint bound to Any -> matches anything
255 // 3) Local endpoint bound to x.y.z.0 -> matches Subnet-directed broadcast packet (e.g.,
256 // x.y.z.255 in a /24 net) and direct destination match.
257
258 if (endP->GetLocalAddress() == daddr)
259 {
260 // Case 1:
261 localAddressMatchesExact = true;
262 }
263 else if (endP->GetLocalAddress() == Ipv4Address::GetAny())
264 {
265 // Case 2:
266 localAddressIsAny = true;
267 }
268 else
269 {
270 // Case 3:
271 for (uint32_t i = 0; i < incomingInterface->GetNAddresses(); i++)
272 {
273 Ipv4InterfaceAddress addr = incomingInterface->GetAddress(i);
274
275 Ipv4Address addrNetpart = addr.GetLocal().CombineMask(addr.GetMask());
276 if (endP->GetLocalAddress() == addrNetpart)
277 {
278 NS_LOG_LOGIC("Endpoint is SubnetDirectedAny "
279 << endP->GetLocalAddress() << "/"
280 << addr.GetMask().GetPrefixLength());
281
282 Ipv4Address daddrNetPart = daddr.CombineMask(addr.GetMask());
283 if (addrNetpart == daddrNetPart)
284 {
285 localAddressIsSubnetAny = true;
286 }
287 }
288 }
289
290 // if no match here, keep looking
291 if (!localAddressIsSubnetAny)
292 {
293 continue;
294 }
295 }
296
297 bool remotePortMatchesExact = endP->GetPeerPort() == sport;
298 bool remotePortMatchesWildCard = endP->GetPeerPort() == 0;
299 bool remoteAddressMatchesExact = endP->GetPeerAddress() == saddr;
300 bool remoteAddressMatchesWildCard = endP->GetPeerAddress() == Ipv4Address::GetAny();
301
302 // If remote does not match either with exact or wildcard,
303 // skip this one
304 if (!(remotePortMatchesExact || remotePortMatchesWildCard))
305 {
306 continue;
307 }
308 if (!(remoteAddressMatchesExact || remoteAddressMatchesWildCard))
309 {
310 continue;
311 }
312
313 bool localAddressMatchesWildCard = localAddressIsAny || localAddressIsSubnetAny;
314
315 if (localAddressMatchesExact && remoteAddressMatchesExact && remotePortMatchesExact)
316 { // All 4 match - this is the case of an open TCP connection, for example.
317 NS_LOG_LOGIC("Found an endpoint for case 4, adding " << endP->GetLocalAddress() << ":"
318 << endP->GetLocalPort());
319 retval4.push_back(endP);
320 }
321 if (localAddressMatchesWildCard && remoteAddressMatchesExact && remotePortMatchesExact)
322 { // All but local address - no idea what this case could be.
323 NS_LOG_LOGIC("Found an endpoint for case 3, adding " << endP->GetLocalAddress() << ":"
324 << endP->GetLocalPort());
325 retval3.push_back(endP);
326 }
327 if (localAddressMatchesExact && remoteAddressMatchesWildCard && remotePortMatchesWildCard)
328 { // Only local port and local address matches exactly - Not yet opened connection
329 NS_LOG_LOGIC("Found an endpoint for case 2, adding " << endP->GetLocalAddress() << ":"
330 << endP->GetLocalPort());
331 retval2.push_back(endP);
332 }
333 if (localAddressMatchesWildCard && remoteAddressMatchesWildCard &&
334 remotePortMatchesWildCard)
335 { // Only local port matches exactly - Endpoint open to "any" connection
336 NS_LOG_LOGIC("Found an endpoint for case 1, adding " << endP->GetLocalAddress() << ":"
337 << endP->GetLocalPort());
338 retval1.push_back(endP);
339 }
340 }
341
342 // Here we find the most exact match
343 EndPoints retval;
344 if (!retval4.empty())
345 {
346 retval = retval4;
347 }
348 else if (!retval3.empty())
349 {
350 retval = retval3;
351 }
352 else if (!retval2.empty())
353 {
354 retval = retval2;
355 }
356 else
357 {
358 retval = retval1;
359 }
360
361 NS_ABORT_MSG_IF(retval.size() > 1,
362 "Too many endpoints - perhaps you created too many sockets without binding "
363 "them to different NetDevices.");
364 return retval; // might be empty if no matches
365}
366
369 uint16_t dport,
370 Ipv4Address saddr,
371 uint16_t sport)
372{
373 NS_LOG_FUNCTION(this << daddr << dport << saddr << sport);
374
375 // this code is a copy/paste version of an old BSD ip stack lookup
376 // function.
377 uint32_t genericity = 3;
378 Ipv4EndPoint* generic = nullptr;
379 for (auto i = m_endPoints.begin(); i != m_endPoints.end(); i++)
380 {
381 if ((*i)->GetLocalPort() != dport)
382 {
383 continue;
384 }
385 if ((*i)->GetLocalAddress() == daddr && (*i)->GetPeerPort() == sport &&
386 (*i)->GetPeerAddress() == saddr)
387 {
388 /* this is an exact match. */
389 return *i;
390 }
391 uint32_t tmp = 0;
392 if ((*i)->GetLocalAddress() == Ipv4Address::GetAny())
393 {
394 tmp++;
395 }
396 if ((*i)->GetPeerAddress() == Ipv4Address::GetAny())
397 {
398 tmp++;
399 }
400 if (tmp < genericity)
401 {
402 generic = (*i);
403 genericity = tmp;
404 }
405 }
406 return generic;
407}
408
409uint16_t
411{
412 // Similar to counting up logic in netinet/in_pcb.c
413 NS_LOG_FUNCTION(this);
414 uint16_t port = m_ephemeral;
415 int count = m_portLast - m_portFirst;
416 do
417 {
418 if (count-- < 0)
419 {
420 return 0;
421 }
422 ++port;
423 if (port < m_portFirst || port > m_portLast)
424 {
426 }
427 } while (LookupPortLocal(port));
429 return port;
430}
431
432} // namespace ns3
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
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.
Definition: ptr.h:77
uint16_t port
Definition: dsdv-manet.cc:44
#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:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#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:261
Every class exported by the ns3 library is enclosed in the ns3 namespace.