A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
ipv4-raw-socket-impl.cc
Go to the documentation of this file.
2
3#include "icmpv4.h"
6
7#include "ns3/boolean.h"
8#include "ns3/inet-socket-address.h"
9#include "ns3/log.h"
10#include "ns3/node.h"
11#include "ns3/packet.h"
12#include "ns3/uinteger.h"
13
14#ifdef __WIN32__
15#include "win32-internet.h"
16#else
17#include <netinet/in.h>
18#include <sys/socket.h>
19#endif
20
21#include <sys/types.h>
22
23namespace ns3
24{
25
26NS_LOG_COMPONENT_DEFINE("Ipv4RawSocketImpl");
27
28NS_OBJECT_ENSURE_REGISTERED(Ipv4RawSocketImpl);
29
30TypeId
32{
33 static TypeId tid =
34 TypeId("ns3::Ipv4RawSocketImpl")
36 .SetGroupName("Internet")
37 .AddAttribute("Protocol",
38 "Protocol number to match.",
41 MakeUintegerChecker<uint16_t>())
42 .AddAttribute("IcmpFilter",
43 "Any icmp header whose type field matches a bit in this filter is "
44 "dropped. Type must be less than 32.",
47 MakeUintegerChecker<uint32_t>())
48 //
49 // from raw (7), linux, returned length of Send/Recv should be
50 //
51 // | IP_HDRINC on | off |
52 // ----------+---------------+-------------+-
53 // Send(Ipv4)| hdr + payload | payload |
54 // Recv(Ipv4)| hdr + payload | hdr+payload |
55 // ----------+---------------+-------------+-
56 .AddAttribute("IpHeaderInclude",
57 "Include IP Header information (a.k.a setsockopt (IP_HDRINCL)).",
58 BooleanValue(false),
61 return tid;
62}
63
65{
66 NS_LOG_FUNCTION(this);
68 m_node = nullptr;
71 m_protocol = 0;
72 m_shutdownSend = false;
73 m_shutdownRecv = false;
74}
75
76void
78{
79 NS_LOG_FUNCTION(this << node);
80 m_node = node;
81}
82
83void
85{
86 NS_LOG_FUNCTION(this);
87 m_node = nullptr;
89}
90
93{
94 NS_LOG_FUNCTION(this);
95 return m_err;
96}
97
100{
101 NS_LOG_FUNCTION(this);
102 return NS3_SOCK_RAW;
103}
104
107{
108 NS_LOG_FUNCTION(this);
109 return m_node;
110}
111
112int
114{
115 NS_LOG_FUNCTION(this << address);
117 {
119 return -1;
120 }
122 m_src = ad.GetIpv4();
123 return 0;
124}
125
126int
128{
129 NS_LOG_FUNCTION(this);
131 return 0;
132}
133
134int
136{
137 NS_LOG_FUNCTION(this);
138 return -1;
139}
140
141int
143{
144 NS_LOG_FUNCTION(this << address);
145 address = InetSocketAddress(m_src, 0);
146 return 0;
147}
148
149int
151{
152 NS_LOG_FUNCTION(this << address);
153
154 if (m_dst == Ipv4Address::GetAny())
155 {
157 return -1;
158 }
159
160 address = InetSocketAddress(m_dst, 0);
161
162 return 0;
163}
164
165int
167{
168 NS_LOG_FUNCTION(this);
169 Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4>();
170 if (ipv4)
171 {
172 ipv4->DeleteRawSocket(this);
173 }
174 return 0;
175}
176
177int
179{
180 NS_LOG_FUNCTION(this);
181 m_shutdownSend = true;
182 return 0;
183}
184
185int
187{
188 NS_LOG_FUNCTION(this);
189 m_shutdownRecv = true;
190 return 0;
191}
192
193int
195{
196 NS_LOG_FUNCTION(this << address);
198 {
201 return -1;
202 }
204 m_dst = ad.GetIpv4();
206
207 return 0;
208}
209
210int
212{
213 NS_LOG_FUNCTION(this);
215 return -1;
216}
217
220{
221 NS_LOG_FUNCTION(this);
222 return 0xffffffff;
223}
224
225int
227{
228 NS_LOG_FUNCTION(this << p << flags);
230 return SendTo(p, flags, to);
231}
232
233int
235{
236 NS_LOG_FUNCTION(this << p << flags << toAddress);
237 if (!InetSocketAddress::IsMatchingType(toAddress))
238 {
240 return -1;
241 }
242 if (m_shutdownSend)
243 {
244 return 0;
245 }
246
248 Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4>();
249 Ipv4Address dst = ad.GetIpv4();
250 Ipv4Address src = m_src;
251 uint8_t tos = GetIpTos();
252
253 uint8_t priority = GetPriority();
254 if (tos)
255 {
256 SocketIpTosTag ipTosTag;
257 ipTosTag.SetTos(tos);
258 // This packet may already have a SocketIpTosTag (see BUG 2440)
259 p->ReplacePacketTag(ipTosTag);
260 priority = IpTos2Priority(tos);
261 }
262 if (priority)
263 {
264 SocketPriorityTag priorityTag;
265 priorityTag.SetPriority(priority);
266 p->ReplacePacketTag(priorityTag);
267 }
268
269 if (IsManualIpTtl() && GetIpTtl() != 0 && !dst.IsMulticast() && !dst.IsBroadcast())
270 {
271 SocketIpTtlTag tag;
272 tag.SetTtl(GetIpTtl());
273 p->AddPacketTag(tag);
274 }
275
276 Ptr<NetDevice> boundNetDevice = m_boundnetdevice;
277
278 if (!m_src.IsAny())
279 {
280 int32_t index = ipv4->GetInterfaceForAddress(m_src);
281 NS_ASSERT(index >= 0);
282 boundNetDevice = ipv4->GetNetDevice(index);
283 }
284
285 bool subnetDirectedBroadcast = false;
286 if (boundNetDevice)
287 {
288 uint32_t iif = ipv4->GetInterfaceForDevice(boundNetDevice);
289 for (uint32_t j = 0; j < ipv4->GetNAddresses(iif); j++)
290 {
291 Ipv4InterfaceAddress ifAddr = ipv4->GetAddress(iif, j);
292 if (dst.IsSubnetDirectedBroadcast(ifAddr.GetMask()))
293 {
294 subnetDirectedBroadcast = true;
295 }
296 }
297 }
298
299 if (dst.IsBroadcast() || subnetDirectedBroadcast)
300 {
301 if (ipv4->GetNInterfaces() == 1)
302 {
303 boundNetDevice = ipv4->GetNetDevice(0);
304 }
305 if (!boundNetDevice)
306 {
307 NS_LOG_DEBUG("dropped because no outgoing route.");
308 return -1;
309 }
310
311 Ipv4Header header;
312 uint32_t pktSize = p->GetSize();
313 if (!m_iphdrincl)
314 {
315 header.SetDestination(dst);
316 header.SetProtocol(m_protocol);
317 Ptr<Ipv4Route> route = Create<Ipv4Route>();
318 route->SetSource(src);
319 route->SetDestination(dst);
320 route->SetOutputDevice(boundNetDevice);
321 route->SetGateway("0.0.0.0");
322 ipv4->Send(p, route->GetSource(), dst, m_protocol, route);
323 }
324 else
325 {
326 p->RemoveHeader(header);
327 dst = header.GetDestination();
328 src = header.GetSource();
329 pktSize += header.GetSerializedSize();
330 Ptr<Ipv4Route> route = Create<Ipv4Route>();
331 route->SetSource(src);
332 route->SetDestination(dst);
333 route->SetOutputDevice(boundNetDevice);
334 route->SetGateway("0.0.0.0");
335 ipv4->SendWithHeader(p, header, route);
336 }
339 return pktSize;
340 }
341
342 if (ipv4->GetRoutingProtocol())
343 {
344 Ipv4Header header;
345 if (!m_iphdrincl)
346 {
347 header.SetDestination(dst);
348 header.SetProtocol(m_protocol);
349 }
350 else
351 {
352 p->RemoveHeader(header);
353 dst = header.GetDestination();
354 src = header.GetSource();
355 }
356 SocketErrno errno_ =
357 ERROR_NOTERROR; // do not use errno as it is the standard C last error number
358 Ptr<Ipv4Route> route;
359 Ptr<NetDevice> oif = m_boundnetdevice; // specify non-zero if bound to a source address
360 if (!oif && src != Ipv4Address::GetAny())
361 {
362 int32_t index = ipv4->GetInterfaceForAddress(src);
363 NS_ASSERT(index >= 0);
364 oif = ipv4->GetNetDevice(index);
365 NS_LOG_LOGIC("Set index " << oif << "from source " << src);
366 }
367
368 // TBD-- we could cache the route and just check its validity
369 route = ipv4->GetRoutingProtocol()->RouteOutput(p, header, oif, errno_);
370 if (route)
371 {
372 NS_LOG_LOGIC("Route exists");
373 uint32_t pktSize = p->GetSize();
374 if (!m_iphdrincl)
375 {
376 ipv4->Send(p, route->GetSource(), dst, m_protocol, route);
377 }
378 else
379 {
380 pktSize += header.GetSerializedSize();
381 ipv4->SendWithHeader(p, header, route);
382 }
385 return pktSize;
386 }
387 else
388 {
389 NS_LOG_DEBUG("dropped because no outgoing route.");
390 return -1;
391 }
392 }
393 return 0;
394}
395
398{
399 NS_LOG_FUNCTION(this);
400 uint32_t rx = 0;
401 for (auto i = m_recv.begin(); i != m_recv.end(); ++i)
402 {
403 rx += (i->packet)->GetSize();
404 }
405 return rx;
406}
407
410{
411 NS_LOG_FUNCTION(this << maxSize << flags);
412 Address tmp;
413 return RecvFrom(maxSize, flags, tmp);
414}
415
418{
419 NS_LOG_FUNCTION(this << maxSize << flags << fromAddress);
420 if (m_recv.empty())
421 {
422 return nullptr;
423 }
424 Data data = m_recv.front();
425 m_recv.pop_front();
426 InetSocketAddress inet = InetSocketAddress(data.fromIp, data.fromProtocol);
427 fromAddress = inet;
428 if (data.packet->GetSize() > maxSize)
429 {
430 Ptr<Packet> first = data.packet->CreateFragment(0, maxSize);
431 if (!(flags & MSG_PEEK))
432 {
433 data.packet->RemoveAtStart(maxSize);
434 }
435 m_recv.push_front(data);
436 return first;
437 }
438 return data.packet;
439}
440
441void
443{
444 NS_LOG_FUNCTION(this << protocol);
445 m_protocol = protocol;
446}
447
448bool
450 Ipv4Header ipHeader,
451 Ptr<Ipv4Interface> incomingInterface)
452{
453 NS_LOG_FUNCTION(this << *p << ipHeader << incomingInterface);
454 if (m_shutdownRecv)
455 {
456 return false;
457 }
458
459 Ptr<NetDevice> boundNetDevice = Socket::GetBoundNetDevice();
460 if (boundNetDevice)
461 {
462 if (boundNetDevice != incomingInterface->GetDevice())
463 {
464 return false;
465 }
466 }
467
468 NS_LOG_LOGIC("src = " << m_src << " dst = " << m_dst);
469 if ((m_src == Ipv4Address::GetAny() || ipHeader.GetDestination() == m_src) &&
470 (m_dst == Ipv4Address::GetAny() || ipHeader.GetSource() == m_dst) &&
471 ipHeader.GetProtocol() == m_protocol)
472 {
473 Ptr<Packet> copy = p->Copy();
474 // Should check via getsockopt ()..
475 if (IsRecvPktInfo())
476 {
478 copy->RemovePacketTag(tag);
479 tag.SetAddress(ipHeader.GetDestination());
480 tag.SetTtl(ipHeader.GetTtl());
481 tag.SetRecvIf(incomingInterface->GetDevice()->GetIfIndex());
482 copy->AddPacketTag(tag);
483 }
484
485 // Check only version 4 options
486 if (IsIpRecvTos())
487 {
488 SocketIpTosTag ipTosTag;
489 ipTosTag.SetTos(ipHeader.GetTos());
490 copy->AddPacketTag(ipTosTag);
491 }
492
493 if (IsIpRecvTtl())
494 {
495 SocketIpTtlTag ipTtlTag;
496 ipTtlTag.SetTtl(ipHeader.GetTtl());
497 copy->AddPacketTag(ipTtlTag);
498 }
499
500 if (m_protocol == 1)
501 {
502 Icmpv4Header icmpHeader;
503 copy->PeekHeader(icmpHeader);
504 uint8_t type = icmpHeader.GetType();
505 if (type < 32 && ((uint32_t(1) << type) & m_icmpFilter))
506 {
507 // filter out icmp packet.
508 return false;
509 }
510 }
511 copy->AddHeader(ipHeader);
512 Data data;
513 data.packet = copy;
514 data.fromIp = ipHeader.GetSource();
515 data.fromProtocol = ipHeader.GetProtocol();
516 m_recv.push_back(data);
518 return true;
519 }
520 return false;
521}
522
523bool
525{
526 NS_LOG_FUNCTION(this << allowBroadcast);
527 return allowBroadcast;
528}
529
530bool
532{
533 NS_LOG_FUNCTION(this);
534 return true;
535}
536
537} // namespace ns3
a polymophic address class
Definition: address.h:101
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Base class for all the ICMP packet headers.
Definition: icmpv4.h:43
uint8_t GetType() const
Get ICMP type.
Definition: icmpv4.cc:130
an Inet address class
static bool IsMatchingType(const Address &address)
Ipv4Address GetIpv4() const
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
bool IsAny() const
static Ipv4Address GetAny()
Packet header for IPv4.
Definition: ipv4-header.h:34
void SetDestination(Ipv4Address destination)
Definition: ipv4-header.cc:309
Ipv4Address GetSource() const
Definition: ipv4-header.cc:302
uint8_t GetTos() const
Definition: ipv4-header.cc:196
uint8_t GetProtocol() const
Definition: ipv4-header.cc:281
Ipv4Address GetDestination() const
Definition: ipv4-header.cc:316
uint32_t GetSerializedSize() const override
Definition: ipv4-header.cc:384
void SetProtocol(uint8_t num)
Definition: ipv4-header.cc:288
uint8_t GetTtl() const
Definition: ipv4-header.cc:274
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:80
a class to store IPv4 address information on an interface
Ipv4Mask GetMask() const
Get the network mask.
This class implements Linux struct pktinfo in order to deliver ancillary information to the socket in...
void SetRecvIf(uint32_t ifindex)
Set the tag's receiving interface.
void SetAddress(Ipv4Address addr)
Set the tag's address.
void SetTtl(uint8_t ttl)
Set the tag's Time to Live Implemented, but not used in the stack yet.
Ptr< Node > GetNode() const override
Return the node this socket is associated with.
Socket::SocketType GetSocketType() const override
Get socket type (NS3_SOCK_RAW)
int GetPeerName(Address &address) const override
Get the peer address of a connected socket.
Ipv4Address m_src
Source address.
std::list< Data > m_recv
Packet waiting to be processed.
int Bind() override
Allocate a local IPv4 endpoint for this socket.
int Send(Ptr< Packet > p, uint32_t flags) override
Send data (or dummy data) to the remote host.
Ipv4Address m_dst
Destination address.
void DoDispose() override
Destructor implementation.
int Close() override
Close a socket.
int Listen() override
Listen for incoming connections.
bool GetAllowBroadcast() const override
Query whether broadcast datagram transmissions are allowed.
uint32_t GetRxAvailable() const override
Return number of bytes which can be returned from one or multiple calls to Recv.
Socket::SocketErrno m_err
Last error number.
void SetProtocol(uint16_t protocol)
Set protocol field.
Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress) override
Read a single packet from the socket and retrieve the sender address.
bool m_iphdrincl
Include IP Header information (a.k.a setsockopt (IP_HDRINCL))
uint16_t m_protocol
Protocol.
Socket::SocketErrno GetErrno() const override
Get last error number.
int Connect(const Address &address) override
Initiate a connection to a remote host.
int Bind6() override
Allocate a local IPv6 endpoint for this socket.
bool SetAllowBroadcast(bool allowBroadcast) override
Configure whether broadcast datagram transmissions are allowed.
bool ForwardUp(Ptr< const Packet > p, Ipv4Header ipHeader, Ptr< Ipv4Interface > incomingInterface)
Forward up to receive method.
uint32_t m_icmpFilter
ICMPv4 filter specification.
bool m_shutdownRecv
Flag to shutdown receive capability.
static TypeId GetTypeId()
Get the type ID of this class.
void SetNode(Ptr< Node > node)
Set the node associated with this socket.
uint32_t GetTxAvailable() const override
Returns the number of bytes which can be sent in a single call to Send.
bool m_shutdownSend
Flag to shutdown send capability.
int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress) override
Send data to a specified peer.
int GetSockName(Address &address) const override
Get socket address.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:522
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
A low-level Socket API based loosely on the BSD Socket API.
Definition: socket.h:68
Ptr< NetDevice > GetBoundNetDevice()
Returns socket's bound NetDevice, if any.
Definition: socket.cc:347
bool IsIpRecvTtl() const
Ask if the socket is currently passing information about IP_TTL up the stack.
Definition: socket.cc:529
Ptr< Packet > Recv()
Read a single packet from the socket.
Definition: socket.cc:174
bool IsManualIpTtl() const
Checks if the socket has a specific IPv4 TTL set.
Definition: socket.cc:374
void NotifySend(uint32_t spaceAvailable)
Notify through the callback (if set) that some data have been sent.
Definition: socket.cc:292
virtual uint8_t GetIpTtl() const
Query the value of IP Time to Live field of this socket.
Definition: socket.cc:517
bool IsRecvPktInfo() const
Get status indicating whether enable/disable packet information to socket.
Definition: socket.cc:361
uint8_t GetIpTos() const
Query the value of IP Type of Service of this socket.
Definition: socket.cc:450
SocketType
Enumeration of the possible socket types.
Definition: socket.h:107
@ NS3_SOCK_RAW
Definition: socket.h:111
static uint8_t IpTos2Priority(uint8_t ipTos)
Return the priority corresponding to a given TOS value.
Definition: socket.cc:399
void NotifyDataRecv()
Notify through the callback (if set) that some data have been received.
Definition: socket.cc:302
Ptr< NetDevice > m_boundnetdevice
the device this socket is bound to (might be null).
Definition: socket.h:1081
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:84
@ ERROR_INVAL
Definition: socket.h:93
@ ERROR_OPNOTSUPP
Definition: socket.h:91
@ ERROR_NOTERROR
Definition: socket.h:85
@ ERROR_NOTCONN
Definition: socket.h:87
bool IsIpRecvTos() const
Ask if the socket is currently passing information about IP Type of Service up the stack.
Definition: socket.cc:462
void NotifyDataSent(uint32_t size)
Notify through the callback (if set) that some data have been sent.
Definition: socket.cc:282
void NotifyConnectionSucceeded()
Notify through the callback (if set) that the connection has been established.
Definition: socket.cc:214
uint8_t GetPriority() const
Query the priority value of this socket.
Definition: socket.cc:393
void DoDispose() override
Destructor implementation.
Definition: socket.cc:312
void NotifyConnectionFailed()
Notify through the callback (if set) that the connection has not been established due to an error.
Definition: socket.cc:224
indicates whether the socket has IP_TOS set.
Definition: socket.h:1271
void SetTos(uint8_t tos)
Set the tag's TOS.
Definition: socket.cc:798
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer.
Definition: socket.h:1124
void SetTtl(uint8_t ttl)
Set the tag's TTL.
Definition: socket.cc:604
indicates whether the socket has a priority set.
Definition: socket.h:1318
void SetPriority(uint8_t priority)
Set the tag's priority.
Definition: socket.cc:854
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
Hold an unsigned integer type.
Definition: uinteger.h:45
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:81
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
#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_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Definition: first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint32_t GetSize(Ptr< const Packet > packet, const WifiMacHeader *hdr, bool isAmpdu)
Return the total size of the packet after WifiMacHeader and FCS trailer have been added.
Definition: wifi-utils.cc:132
uint8_t data[writeSize]
IPv4 raw data and additional information.
uint32_t pktSize
packet size used for the simulation (in bytes)