A Discrete-Event Network Simulator
API
ipv4-raw-socket-impl.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 #include <netinet/in.h>
3 #include <sys/socket.h>
4 #include <sys/types.h>
5 #include "ipv4-raw-socket-impl.h"
6 #include "ipv4-l3-protocol.h"
7 #include "icmpv4.h"
8 #include "ns3/ipv4-packet-info-tag.h"
9 #include "ns3/inet-socket-address.h"
10 #include "ns3/node.h"
11 #include "ns3/packet.h"
12 #include "ns3/uinteger.h"
13 #include "ns3/boolean.h"
14 #include "ns3/log.h"
15 
16 namespace ns3 {
17 
18 NS_LOG_COMPONENT_DEFINE ("Ipv4RawSocketImpl");
19 
20 NS_OBJECT_ENSURE_REGISTERED (Ipv4RawSocketImpl);
21 
22 TypeId
24 {
25  static TypeId tid = TypeId ("ns3::Ipv4RawSocketImpl")
26  .SetParent<Socket> ()
27  .SetGroupName ("Internet")
28  .AddAttribute ("Protocol", "Protocol number to match.",
29  UintegerValue (0),
31  MakeUintegerChecker<uint16_t> ())
32  .AddAttribute ("IcmpFilter",
33  "Any icmp header whose type field matches a bit in this filter is dropped. Type must be less than 32.",
34  UintegerValue (0),
36  MakeUintegerChecker<uint32_t> ())
37  //
38  // from raw (7), linux, returned length of Send/Recv should be
39  //
40  // | IP_HDRINC on | off |
41  // ----------+---------------+-------------+-
42  // Send(Ipv4)| hdr + payload | payload |
43  // Recv(Ipv4)| hdr + payload | hdr+payload |
44  // ----------+---------------+-------------+-
45  .AddAttribute ("IpHeaderInclude",
46  "Include IP Header information (a.k.a setsockopt (IP_HDRINCL)).",
47  BooleanValue (false),
50  ;
51  return tid;
52 }
53 
55 {
56  NS_LOG_FUNCTION (this);
58  m_node = 0;
61  m_protocol = 0;
62  m_shutdownSend = false;
63  m_shutdownRecv = false;
64 }
65 
66 void
68 {
69  NS_LOG_FUNCTION (this << node);
70  m_node = node;
71 }
72 
73 void
75 {
76  NS_LOG_FUNCTION (this);
77  m_node = 0;
79 }
80 
82 Ipv4RawSocketImpl::GetErrno (void) const
83 {
84  NS_LOG_FUNCTION (this);
85  return m_err;
86 }
87 
90 {
91  NS_LOG_FUNCTION (this);
92  return NS3_SOCK_RAW;
93 }
94 
95 Ptr<Node>
97 {
98  NS_LOG_FUNCTION (this);
99  return m_node;
100 }
101 int
103 {
104  NS_LOG_FUNCTION (this << address);
106  {
108  return -1;
109  }
111  m_src = ad.GetIpv4 ();
112  return 0;
113 }
114 int
116 {
117  NS_LOG_FUNCTION (this);
119  return 0;
120 }
121 int
123 {
124  NS_LOG_FUNCTION (this);
125  return (-1);
126 }
127 int
129 {
130  NS_LOG_FUNCTION (this << address);
132  return 0;
133 }
134 int
136 {
137  NS_LOG_FUNCTION (this << address);
138 
139  if (m_dst == Ipv4Address::GetAny ())
140  {
142  return -1;
143  }
144 
146 
147  return 0;
148 }
149 int
151 {
152  NS_LOG_FUNCTION (this);
153  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
154  if (ipv4 != 0)
155  {
156  ipv4->DeleteRawSocket (this);
157  }
158  return 0;
159 }
160 int
162 {
163  NS_LOG_FUNCTION (this);
164  m_shutdownSend = true;
165  return 0;
166 }
167 int
169 {
170  NS_LOG_FUNCTION (this);
171  m_shutdownRecv = true;
172  return 0;
173 }
174 int
176 {
177  NS_LOG_FUNCTION (this << address);
179  {
181  return -1;
182  }
184  m_dst = ad.GetIpv4 ();
185  SetIpTos (ad.GetTos ());
186 
187  return 0;
188 }
189 int
191 {
192  NS_LOG_FUNCTION (this);
194  return -1;
195 }
196 uint32_t
198 {
199  NS_LOG_FUNCTION (this);
200  return 0xffffffff;
201 }
202 int
204 {
205  NS_LOG_FUNCTION (this << p << flags);
207  to.SetTos (GetIpTos ());
208  return SendTo (p, flags, to);
209 }
210 int
212  const Address &toAddress)
213 {
214  NS_LOG_FUNCTION (this << p << flags << toAddress);
215  if (!InetSocketAddress::IsMatchingType (toAddress))
216  {
218  return -1;
219  }
220  if (m_shutdownSend)
221  {
222  return 0;
223  }
224 
226  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
227  Ipv4Address dst = ad.GetIpv4 ();
228  Ipv4Address src = m_src;
229  uint8_t tos = ad.GetTos ();
230 
231  uint8_t priority = GetPriority ();
232  if (tos)
233  {
234  SocketIpTosTag ipTosTag;
235  ipTosTag.SetTos (tos);
236  // This packet may already have a SocketIpTosTag (see BUG 2440)
237  p->ReplacePacketTag (ipTosTag);
238  priority = IpTos2Priority (tos);
239  }
240  if (priority)
241  {
242  SocketPriorityTag priorityTag;
243  priorityTag.SetPriority (priority);
244  p->ReplacePacketTag (priorityTag);
245  }
246 
247  if (IsManualIpTtl () && GetIpTtl () != 0 && !dst.IsMulticast () && !dst.IsBroadcast ())
248  {
249  SocketIpTtlTag tag;
250  tag.SetTtl (GetIpTtl ());
251  p->AddPacketTag (tag);
252  }
253 
254  bool subnetDirectedBroadcast = false;
255  if (m_boundnetdevice)
256  {
257  uint32_t iif = ipv4->GetInterfaceForDevice (m_boundnetdevice);
258  for (uint32_t j = 0; j < ipv4->GetNAddresses (iif); j++)
259  {
260  Ipv4InterfaceAddress ifAddr = ipv4->GetAddress (iif, j);
261  if (dst.IsSubnetDirectedBroadcast (ifAddr.GetMask ()))
262  {
263  subnetDirectedBroadcast = true;
264  }
265  }
266  }
267 
268  if (dst.IsBroadcast () || subnetDirectedBroadcast)
269  {
270  Ptr <NetDevice> boundNetDevice = m_boundnetdevice;
271  if (ipv4->GetNInterfaces () == 1)
272  {
273  boundNetDevice = ipv4->GetNetDevice (0);
274  }
275  if (boundNetDevice == 0)
276  {
277  NS_LOG_DEBUG ("dropped because no outgoing route.");
278  return -1;
279  }
280 
281  Ipv4Header header;
282  uint32_t pktSize = p->GetSize ();
283  if (!m_iphdrincl)
284  {
285  header.SetDestination (dst);
286  header.SetProtocol (m_protocol);
287  Ptr<Ipv4Route> route = Create <Ipv4Route> ();
288  route->SetSource (src);
289  route->SetDestination (dst);
290  route->SetOutputDevice (boundNetDevice);
291  ipv4->Send (p, route->GetSource (), dst, m_protocol, route);
292  }
293  else
294  {
295  p->RemoveHeader (header);
296  dst = header.GetDestination ();
297  src = header.GetSource ();
298  pktSize += header.GetSerializedSize ();
299  Ptr<Ipv4Route> route = Create <Ipv4Route> ();
300  route->SetSource (src);
301  route->SetDestination (dst);
302  route->SetOutputDevice (boundNetDevice);
303  ipv4->SendWithHeader (p, header, route);
304  }
307  return pktSize;
308  }
309 
310 
311  if (ipv4->GetRoutingProtocol ())
312  {
313  Ipv4Header header;
314  if (!m_iphdrincl)
315  {
316  header.SetDestination (dst);
317  header.SetProtocol (m_protocol);
318  }
319  else
320  {
321  p->RemoveHeader (header);
322  dst = header.GetDestination ();
323  src = header.GetSource ();
324  }
325  SocketErrno errno_ = ERROR_NOTERROR; //do not use errno as it is the standard C last error number
326  Ptr<Ipv4Route> route;
327  Ptr<NetDevice> oif = m_boundnetdevice; //specify non-zero if bound to a source address
328  if (!oif && src != Ipv4Address::GetAny ())
329  {
330  int32_t index = ipv4->GetInterfaceForAddress (src);
331  NS_ASSERT (index >= 0);
332  oif = ipv4->GetNetDevice (index);
333  NS_LOG_LOGIC ("Set index " << oif << "from source " << src);
334  }
335 
336  // TBD-- we could cache the route and just check its validity
337  route = ipv4->GetRoutingProtocol ()->RouteOutput (p, header, oif, errno_);
338  if (route != 0)
339  {
340  NS_LOG_LOGIC ("Route exists");
341  uint32_t pktSize = p->GetSize ();
342  if (!m_iphdrincl)
343  {
344  ipv4->Send (p, route->GetSource (), dst, m_protocol, route);
345  }
346  else
347  {
348  pktSize += header.GetSerializedSize ();
349  ipv4->SendWithHeader (p, header, route);
350  }
353  return pktSize;
354  }
355  else
356  {
357  NS_LOG_DEBUG ("dropped because no outgoing route.");
358  return -1;
359  }
360  }
361  return 0;
362 }
363 uint32_t
365 {
366  NS_LOG_FUNCTION (this);
367  uint32_t rx = 0;
368  for (std::list<Data>::const_iterator i = m_recv.begin (); i != m_recv.end (); ++i)
369  {
370  rx += (i->packet)->GetSize ();
371  }
372  return rx;
373 }
375 Ipv4RawSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
376 {
377  NS_LOG_FUNCTION (this << maxSize << flags);
378  Address tmp;
379  return RecvFrom (maxSize, flags, tmp);
380 }
382 Ipv4RawSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags,
383  Address &fromAddress)
384 {
385  NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
386  if (m_recv.empty ())
387  {
388  return 0;
389  }
390  struct Data data = m_recv.front ();
391  m_recv.pop_front ();
392  InetSocketAddress inet = InetSocketAddress (data.fromIp, data.fromProtocol);
393  fromAddress = inet;
394  if (data.packet->GetSize () > maxSize)
395  {
396  Ptr<Packet> first = data.packet->CreateFragment (0, maxSize);
397  if (!(flags & MSG_PEEK))
398  {
399  data.packet->RemoveAtStart (maxSize);
400  }
401  m_recv.push_front (data);
402  return first;
403  }
404  return data.packet;
405 }
406 
407 void
409 {
410  NS_LOG_FUNCTION (this << protocol);
411  m_protocol = protocol;
412 }
413 
414 bool
416 {
417  NS_LOG_FUNCTION (this << *p << ipHeader << incomingInterface);
418  if (m_shutdownRecv)
419  {
420  return false;
421  }
422 
423  Ptr<NetDevice> boundNetDevice = Socket::GetBoundNetDevice();
424  if (boundNetDevice)
425  {
426  if (boundNetDevice != incomingInterface->GetDevice())
427  {
428  return false;
429  }
430  }
431 
432  NS_LOG_LOGIC ("src = " << m_src << " dst = " << m_dst);
433  if ((m_src == Ipv4Address::GetAny () || ipHeader.GetDestination () == m_src) &&
434  (m_dst == Ipv4Address::GetAny () || ipHeader.GetSource () == m_dst) &&
435  ipHeader.GetProtocol () == m_protocol)
436  {
437  Ptr<Packet> copy = p->Copy ();
438  // Should check via getsockopt ()..
439  if (IsRecvPktInfo ())
440  {
441  Ipv4PacketInfoTag tag;
442  copy->RemovePacketTag (tag);
443  tag.SetAddress (ipHeader.GetDestination ());
444  tag.SetTtl (ipHeader.GetTtl ());
445  tag.SetRecvIf (incomingInterface->GetDevice ()->GetIfIndex ());
446  copy->AddPacketTag (tag);
447  }
448 
449  //Check only version 4 options
450  if (IsIpRecvTos ())
451  {
452  SocketIpTosTag ipTosTag;
453  ipTosTag.SetTos (ipHeader.GetTos ());
454  copy->AddPacketTag (ipTosTag);
455  }
456 
457  if (IsIpRecvTtl ())
458  {
459  SocketIpTtlTag ipTtlTag;
460  ipTtlTag.SetTtl (ipHeader.GetTtl ());
461  copy->AddPacketTag (ipTtlTag);
462  }
463 
464  if (m_protocol == 1)
465  {
466  Icmpv4Header icmpHeader;
467  copy->PeekHeader (icmpHeader);
468  uint8_t type = icmpHeader.GetType ();
469  if (type < 32 &&
470  ((uint32_t(1) << type) & m_icmpFilter))
471  {
472  // filter out icmp packet.
473  return false;
474  }
475  }
476  copy->AddHeader (ipHeader);
477  struct Data data;
478  data.packet = copy;
479  data.fromIp = ipHeader.GetSource ();
480  data.fromProtocol = ipHeader.GetProtocol ();
481  m_recv.push_back (data);
482  NotifyDataRecv ();
483  return true;
484  }
485  return false;
486 }
487 
488 bool
490 {
491  NS_LOG_FUNCTION (this << allowBroadcast);
492  if (!allowBroadcast)
493  {
494  return false;
495  }
496  return true;
497 }
498 
499 bool
501 {
502  NS_LOG_FUNCTION (this);
503  return true;
504 }
505 
506 } // namespace ns3
a polymophic address class
Definition: address.h:91
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Base class for all the ICMP packet headers.
Definition: icmpv4.h:41
uint8_t GetType(void) const
Get ICMP type.
Definition: icmpv4.cc:121
an Inet address class
uint8_t GetTos(void) const
Ipv4Address GetIpv4(void) const
static bool IsMatchingType(const Address &address)
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:41
static Ipv4Address GetAny(void)
Packet header for IPv4.
Definition: ipv4-header.h:34
void SetDestination(Ipv4Address destination)
Definition: ipv4-header.cc:298
virtual uint32_t GetSerializedSize(void) const
Definition: ipv4-header.cc:375
uint8_t GetTos(void) const
Definition: ipv4-header.cc:194
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:291
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:304
uint8_t GetProtocol(void) const
Definition: ipv4-header.cc:272
void SetProtocol(uint8_t num)
Definition: ipv4-header.cc:278
uint8_t GetTtl(void) const
Definition: ipv4-header.cc:265
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:77
a class to store IPv4 address information on an interface
Ipv4Mask GetMask(void) const
Get the network mask.
Ptr< NetDevice > GetDevice(void) 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.
virtual int GetPeerName(Address &address) const
Get the peer address of a connected socket.
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)
Send data to a specified peer.
virtual int ShutdownSend(void)
Ipv4Address m_src
Source address.
virtual int ShutdownRecv(void)
virtual int Bind()
Allocate a local IPv4 endpoint for this socket.
virtual int Connect(const Address &address)
Initiate a connection to a remote host.
virtual uint32_t GetRxAvailable(void) const
Return number of bytes which can be returned from one or multiple calls to Recv.
virtual void DoDispose(void)
Destructor implementation.
Ipv4Address m_dst
Destination address.
static TypeId GetTypeId(void)
Get the type ID of this class.
std::list< struct Data > m_recv
Packet waiting to be processed.
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)
Read a single packet from the socket and retrieve the sender address.
virtual enum Socket::SocketType GetSocketType(void) const
Get socket type (NS3_SOCK_RAW)
void SetProtocol(uint16_t protocol)
Set protocol field.
virtual int Close(void)
Close a socket.
virtual int GetSockName(Address &address) const
Get socket address.
bool m_iphdrincl
Include IP Header information (a.k.a setsockopt (IP_HDRINCL))
uint16_t m_protocol
Protocol.
virtual bool GetAllowBroadcast() const
Query whether broadcast datagram transmissions are allowed.
virtual bool SetAllowBroadcast(bool allowBroadcast)
Configure whether broadcast datagram transmissions are allowed.
virtual int Listen(void)
Listen for incoming connections.
enum Socket::SocketErrno m_err
Last error number.
virtual uint32_t GetTxAvailable(void) const
Returns the number of bytes which can be sent in a single call to Send.
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.
virtual Ptr< Node > GetNode(void) const
Return the node this socket is associated with.
void SetNode(Ptr< Node > node)
Set the node associated with this socket.
virtual int Bind6()
Allocate a local IPv6 endpoint for this socket.
virtual enum Socket::SocketErrno GetErrno() const
Get last error number.
bool m_shutdownSend
Flag to shutdown send capability.
virtual int Send(Ptr< Packet > p, uint32_t flags)
Send data (or dummy data) to the remote host.
virtual uint32_t GetIfIndex(void) const =0
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:963
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
bool ReplacePacketTag(Tag &tag)
Replace the value of a packet tag.
Definition: packet.cc:970
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
A low-level Socket API based loosely on the BSD Socket API.
Definition: socket.h:67
Ptr< NetDevice > GetBoundNetDevice()
Returns socket's bound NetDevice, if any.
Definition: socket.cc:351
uint8_t GetPriority(void) const
Query the priority value of this socket.
Definition: socket.cc:396
bool IsIpRecvTtl(void) const
Ask if the socket is currently passing information about IP_TTL up the stack.
Definition: socket.cc:532
void SetIpTos(uint8_t ipTos)
Manually set IP Type of Service field.
Definition: socket.cc:437
void NotifySend(uint32_t spaceAvailable)
Notify through the callback (if set) that some data have been sent.
Definition: socket.cc:295
bool IsRecvPktInfo() const
Get status indicating whether enable/disable packet information to socket.
Definition: socket.cc:364
virtual void DoDispose(void)
Destructor implementation.
Definition: socket.cc:315
SocketType
Enumeration of the possible socket types.
Definition: socket.h:104
@ NS3_SOCK_RAW
Definition: socket.h:108
static uint8_t IpTos2Priority(uint8_t ipTos)
Return the priority corresponding to a given TOS value.
Definition: socket.cc:402
bool IsManualIpTtl(void) const
Checks if the socket has a specific IPv4 TTL set.
Definition: socket.cc:377
bool IsIpRecvTos(void) const
Ask if the socket is currently passing information about IP Type of Service up the stack.
Definition: socket.cc:465
void NotifyDataRecv(void)
Notify through the callback (if set) that some data have been received.
Definition: socket.cc:305
Ptr< NetDevice > m_boundnetdevice
the device this socket is bound to (might be null).
Definition: socket.h:1077
virtual uint8_t GetIpTtl(void) const
Query the value of IP Time to Live field of this socket.
Definition: socket.cc:520
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
@ ERROR_INVAL
Definition: socket.h:91
@ ERROR_OPNOTSUPP
Definition: socket.h:89
@ ERROR_NOTERROR
Definition: socket.h:83
@ ERROR_NOTCONN
Definition: socket.h:85
void NotifyDataSent(uint32_t size)
Notify through the callback (if set) that some data have been sent.
Definition: socket.cc:285
uint8_t GetIpTos(void) const
Query the value of IP Type of Service of this socket.
Definition: socket.cc:453
Ptr< Packet > Recv(void)
Read a single packet from the socket.
Definition: socket.cc:175
indicates whether the socket has IP_TOS set.
Definition: socket.h:1263
void SetTos(uint8_t tos)
Set the tag's TOS.
Definition: socket.cc:785
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer.
Definition: socket.h:1117
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:1309
void SetPriority(uint8_t priority)
Set the tag's priority.
Definition: socket.cc:842
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Hold an unsigned integer type.
Definition: uinteger.h:44
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: boolean.h:85
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h:45
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#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:45
Definition: first.py:1
address
Definition: first.py:44
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:129
uint8_t data[writeSize]
IPv4 raw data and additional information.
uint32_t pktSize
packet size used for the simulation (in bytes)
Definition: wifi-bianchi.cc:89