A Discrete-Event Network Simulator
API
ipv4-raw-socket-impl.cc
Go to the documentation of this file.
1 #include "ipv4-raw-socket-impl.h"
2 
3 #include "icmpv4.h"
4 #include "ipv4-packet-info-tag.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 
23 namespace ns3
24 {
25 
26 NS_LOG_COMPONENT_DEFINE("Ipv4RawSocketImpl");
27 
28 NS_OBJECT_ENSURE_REGISTERED(Ipv4RawSocketImpl);
29 
30 TypeId
32 {
33  static TypeId tid =
34  TypeId("ns3::Ipv4RawSocketImpl")
35  .SetParent<Socket>()
36  .SetGroupName("Internet")
37  .AddAttribute("Protocol",
38  "Protocol number to match.",
39  UintegerValue(0),
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.",
45  UintegerValue(0),
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 
76 void
78 {
79  NS_LOG_FUNCTION(this << node);
80  m_node = node;
81 }
82 
83 void
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 
105 Ptr<Node>
107 {
108  NS_LOG_FUNCTION(this);
109  return m_node;
110 }
111 
112 int
114 {
115  NS_LOG_FUNCTION(this << address);
117  {
119  return -1;
120  }
122  m_src = ad.GetIpv4();
123  return 0;
124 }
125 
126 int
128 {
129  NS_LOG_FUNCTION(this);
131  return 0;
132 }
133 
134 int
136 {
137  NS_LOG_FUNCTION(this);
138  return -1;
139 }
140 
141 int
143 {
144  NS_LOG_FUNCTION(this << address);
146  return 0;
147 }
148 
149 int
151 {
152  NS_LOG_FUNCTION(this << address);
153 
154  if (m_dst == Ipv4Address::GetAny())
155  {
157  return -1;
158  }
159 
161 
162  return 0;
163 }
164 
165 int
167 {
168  NS_LOG_FUNCTION(this);
170  if (ipv4)
171  {
172  ipv4->DeleteRawSocket(this);
173  }
174  return 0;
175 }
176 
177 int
179 {
180  NS_LOG_FUNCTION(this);
181  m_shutdownSend = true;
182  return 0;
183 }
184 
185 int
187 {
188  NS_LOG_FUNCTION(this);
189  m_shutdownRecv = true;
190  return 0;
191 }
192 
193 int
195 {
196  NS_LOG_FUNCTION(this << address);
198  {
201  return -1;
202  }
204  m_dst = ad.GetIpv4();
205  SetIpTos(ad.GetTos());
207 
208  return 0;
209 }
210 
211 int
213 {
214  NS_LOG_FUNCTION(this);
216  return -1;
217 }
218 
219 uint32_t
221 {
222  NS_LOG_FUNCTION(this);
223  return 0xffffffff;
224 }
225 
226 int
228 {
229  NS_LOG_FUNCTION(this << p << flags);
231  to.SetTos(GetIpTos());
232  return SendTo(p, flags, to);
233 }
234 
235 int
236 Ipv4RawSocketImpl::SendTo(Ptr<Packet> p, uint32_t flags, const Address& toAddress)
237 {
238  NS_LOG_FUNCTION(this << p << flags << toAddress);
239  if (!InetSocketAddress::IsMatchingType(toAddress))
240  {
242  return -1;
243  }
244  if (m_shutdownSend)
245  {
246  return 0;
247  }
248 
251  Ipv4Address dst = ad.GetIpv4();
252  Ipv4Address src = m_src;
253  uint8_t tos = ad.GetTos();
254 
255  uint8_t priority = GetPriority();
256  if (tos)
257  {
258  SocketIpTosTag ipTosTag;
259  ipTosTag.SetTos(tos);
260  // This packet may already have a SocketIpTosTag (see BUG 2440)
261  p->ReplacePacketTag(ipTosTag);
262  priority = IpTos2Priority(tos);
263  }
264  if (priority)
265  {
266  SocketPriorityTag priorityTag;
267  priorityTag.SetPriority(priority);
268  p->ReplacePacketTag(priorityTag);
269  }
270 
271  if (IsManualIpTtl() && GetIpTtl() != 0 && !dst.IsMulticast() && !dst.IsBroadcast())
272  {
273  SocketIpTtlTag tag;
274  tag.SetTtl(GetIpTtl());
275  p->AddPacketTag(tag);
276  }
277 
278  Ptr<NetDevice> boundNetDevice = m_boundnetdevice;
279 
280  if (!m_src.IsAny())
281  {
282  int32_t index = ipv4->GetInterfaceForAddress(m_src);
283  NS_ASSERT(index >= 0);
284  boundNetDevice = ipv4->GetNetDevice(index);
285  }
286 
287  bool subnetDirectedBroadcast = false;
288  if (boundNetDevice)
289  {
290  uint32_t iif = ipv4->GetInterfaceForDevice(boundNetDevice);
291  for (uint32_t j = 0; j < ipv4->GetNAddresses(iif); j++)
292  {
293  Ipv4InterfaceAddress ifAddr = ipv4->GetAddress(iif, j);
294  if (dst.IsSubnetDirectedBroadcast(ifAddr.GetMask()))
295  {
296  subnetDirectedBroadcast = true;
297  }
298  }
299  }
300 
301  if (dst.IsBroadcast() || subnetDirectedBroadcast)
302  {
303  if (ipv4->GetNInterfaces() == 1)
304  {
305  boundNetDevice = ipv4->GetNetDevice(0);
306  }
307  if (!boundNetDevice)
308  {
309  NS_LOG_DEBUG("dropped because no outgoing route.");
310  return -1;
311  }
312 
313  Ipv4Header header;
314  uint32_t pktSize = p->GetSize();
315  if (!m_iphdrincl)
316  {
317  header.SetDestination(dst);
318  header.SetProtocol(m_protocol);
319  Ptr<Ipv4Route> route = Create<Ipv4Route>();
320  route->SetSource(src);
321  route->SetDestination(dst);
322  route->SetOutputDevice(boundNetDevice);
323  route->SetGateway("0.0.0.0");
324  ipv4->Send(p, route->GetSource(), dst, m_protocol, route);
325  }
326  else
327  {
328  p->RemoveHeader(header);
329  dst = header.GetDestination();
330  src = header.GetSource();
331  pktSize += header.GetSerializedSize();
332  Ptr<Ipv4Route> route = Create<Ipv4Route>();
333  route->SetSource(src);
334  route->SetDestination(dst);
335  route->SetOutputDevice(boundNetDevice);
336  route->SetGateway("0.0.0.0");
337  ipv4->SendWithHeader(p, header, route);
338  }
341  return pktSize;
342  }
343 
344  if (ipv4->GetRoutingProtocol())
345  {
346  Ipv4Header header;
347  if (!m_iphdrincl)
348  {
349  header.SetDestination(dst);
350  header.SetProtocol(m_protocol);
351  }
352  else
353  {
354  p->RemoveHeader(header);
355  dst = header.GetDestination();
356  src = header.GetSource();
357  }
358  SocketErrno errno_ =
359  ERROR_NOTERROR; // do not use errno as it is the standard C last error number
360  Ptr<Ipv4Route> route;
361  Ptr<NetDevice> oif = m_boundnetdevice; // specify non-zero if bound to a source address
362  if (!oif && src != Ipv4Address::GetAny())
363  {
364  int32_t index = ipv4->GetInterfaceForAddress(src);
365  NS_ASSERT(index >= 0);
366  oif = ipv4->GetNetDevice(index);
367  NS_LOG_LOGIC("Set index " << oif << "from source " << src);
368  }
369 
370  // TBD-- we could cache the route and just check its validity
371  route = ipv4->GetRoutingProtocol()->RouteOutput(p, header, oif, errno_);
372  if (route)
373  {
374  NS_LOG_LOGIC("Route exists");
375  uint32_t pktSize = p->GetSize();
376  if (!m_iphdrincl)
377  {
378  ipv4->Send(p, route->GetSource(), dst, m_protocol, route);
379  }
380  else
381  {
382  pktSize += header.GetSerializedSize();
383  ipv4->SendWithHeader(p, header, route);
384  }
387  return pktSize;
388  }
389  else
390  {
391  NS_LOG_DEBUG("dropped because no outgoing route.");
392  return -1;
393  }
394  }
395  return 0;
396 }
397 
398 uint32_t
400 {
401  NS_LOG_FUNCTION(this);
402  uint32_t rx = 0;
403  for (auto i = m_recv.begin(); i != m_recv.end(); ++i)
404  {
405  rx += (i->packet)->GetSize();
406  }
407  return rx;
408 }
409 
411 Ipv4RawSocketImpl::Recv(uint32_t maxSize, uint32_t flags)
412 {
413  NS_LOG_FUNCTION(this << maxSize << flags);
414  Address tmp;
415  return RecvFrom(maxSize, flags, tmp);
416 }
417 
419 Ipv4RawSocketImpl::RecvFrom(uint32_t maxSize, uint32_t flags, Address& fromAddress)
420 {
421  NS_LOG_FUNCTION(this << maxSize << flags << fromAddress);
422  if (m_recv.empty())
423  {
424  return nullptr;
425  }
426  Data data = m_recv.front();
427  m_recv.pop_front();
428  InetSocketAddress inet = InetSocketAddress(data.fromIp, data.fromProtocol);
429  fromAddress = inet;
430  if (data.packet->GetSize() > maxSize)
431  {
432  Ptr<Packet> first = data.packet->CreateFragment(0, maxSize);
433  if (!(flags & MSG_PEEK))
434  {
435  data.packet->RemoveAtStart(maxSize);
436  }
437  m_recv.push_front(data);
438  return first;
439  }
440  return data.packet;
441 }
442 
443 void
445 {
446  NS_LOG_FUNCTION(this << protocol);
447  m_protocol = protocol;
448 }
449 
450 bool
452  Ipv4Header ipHeader,
453  Ptr<Ipv4Interface> incomingInterface)
454 {
455  NS_LOG_FUNCTION(this << *p << ipHeader << incomingInterface);
456  if (m_shutdownRecv)
457  {
458  return false;
459  }
460 
461  Ptr<NetDevice> boundNetDevice = Socket::GetBoundNetDevice();
462  if (boundNetDevice)
463  {
464  if (boundNetDevice != incomingInterface->GetDevice())
465  {
466  return false;
467  }
468  }
469 
470  NS_LOG_LOGIC("src = " << m_src << " dst = " << m_dst);
471  if ((m_src == Ipv4Address::GetAny() || ipHeader.GetDestination() == m_src) &&
472  (m_dst == Ipv4Address::GetAny() || ipHeader.GetSource() == m_dst) &&
473  ipHeader.GetProtocol() == m_protocol)
474  {
475  Ptr<Packet> copy = p->Copy();
476  // Should check via getsockopt ()..
477  if (IsRecvPktInfo())
478  {
479  Ipv4PacketInfoTag tag;
480  copy->RemovePacketTag(tag);
481  tag.SetAddress(ipHeader.GetDestination());
482  tag.SetTtl(ipHeader.GetTtl());
483  tag.SetRecvIf(incomingInterface->GetDevice()->GetIfIndex());
484  copy->AddPacketTag(tag);
485  }
486 
487  // Check only version 4 options
488  if (IsIpRecvTos())
489  {
490  SocketIpTosTag ipTosTag;
491  ipTosTag.SetTos(ipHeader.GetTos());
492  copy->AddPacketTag(ipTosTag);
493  }
494 
495  if (IsIpRecvTtl())
496  {
497  SocketIpTtlTag ipTtlTag;
498  ipTtlTag.SetTtl(ipHeader.GetTtl());
499  copy->AddPacketTag(ipTtlTag);
500  }
501 
502  if (m_protocol == 1)
503  {
504  Icmpv4Header icmpHeader;
505  copy->PeekHeader(icmpHeader);
506  uint8_t type = icmpHeader.GetType();
507  if (type < 32 && ((uint32_t(1) << type) & m_icmpFilter))
508  {
509  // filter out icmp packet.
510  return false;
511  }
512  }
513  copy->AddHeader(ipHeader);
514  Data data;
515  data.packet = copy;
516  data.fromIp = ipHeader.GetSource();
517  data.fromProtocol = ipHeader.GetProtocol();
518  m_recv.push_back(data);
519  NotifyDataRecv();
520  return true;
521  }
522  return false;
523 }
524 
525 bool
527 {
528  NS_LOG_FUNCTION(this << allowBroadcast);
529  return allowBroadcast;
530 }
531 
532 bool
534 {
535  NS_LOG_FUNCTION(this);
536  return true;
537 }
538 
539 } // namespace ns3
a polymophic address class
Definition: address.h:101
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.
Ptr< NetDevice > GetDevice() const
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:471
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:967
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:960
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:305
bool ReplacePacketTag(Tag &tag)
Replace the value of a packet tag.
Definition: packet.cc:975
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 SetIpTos(uint8_t ipTos)
Manually set IP Type of Service field.
Definition: socket.cc:434
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:1079
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:1269
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:1122
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:1316
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:931
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
#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
address
Definition: first.py:47
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
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)