A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 NS_LOG_COMPONENT_DEFINE ("Ipv4RawSocketImpl");
17 
18 namespace ns3 {
19 
20 NS_OBJECT_ENSURE_REGISTERED (Ipv4RawSocketImpl);
21 
22 TypeId
24 {
25  static TypeId tid = TypeId ("ns3::Ipv4RawSocketImpl")
26  .SetParent<Socket> ()
27  .AddAttribute ("Protocol", "Protocol number to match.",
28  UintegerValue (0),
29  MakeUintegerAccessor (&Ipv4RawSocketImpl::m_protocol),
30  MakeUintegerChecker<uint16_t> ())
31  .AddAttribute ("IcmpFilter",
32  "Any icmp header whose type field matches a bit in this filter is dropped. Type must be less than 32.",
33  UintegerValue (0),
34  MakeUintegerAccessor (&Ipv4RawSocketImpl::m_icmpFilter),
35  MakeUintegerChecker<uint32_t> ())
36  //
37  // from raw (7), linux, returned length of Send/Recv should be
38  //
39  // | IP_HDRINC on | off |
40  // ----------+---------------+-------------+-
41  // Send(Ipv4)| hdr + payload | payload |
42  // Recv(Ipv4)| hdr + payload | hdr+payload |
43  // ----------+---------------+-------------+-
44  .AddAttribute ("IpHeaderInclude",
45  "Include IP Header information (a.k.a setsockopt (IP_HDRINCL)).",
46  BooleanValue (false),
47  MakeBooleanAccessor (&Ipv4RawSocketImpl::m_iphdrincl),
48  MakeBooleanChecker ())
49  ;
50  return tid;
51 }
52 
54 {
55  NS_LOG_FUNCTION (this);
57  m_node = 0;
60  m_protocol = 0;
61  m_shutdownSend = false;
62  m_shutdownRecv = false;
63 }
64 
65 void
67 {
68  m_node = node;
69 }
70 
71 void
73 {
74  NS_LOG_FUNCTION (this);
75  m_node = 0;
77 }
78 
81 {
82  NS_LOG_FUNCTION (this);
83  return m_err;
84 }
85 
88 {
89  return NS3_SOCK_RAW;
90 }
91 
92 Ptr<Node>
94 {
95  NS_LOG_FUNCTION (this);
96  return m_node;
97 }
98 int
100 {
101  NS_LOG_FUNCTION (this << address);
102  if (!InetSocketAddress::IsMatchingType (address))
103  {
105  return -1;
106  }
108  m_src = ad.GetIpv4 ();
109  return 0;
110 }
111 int
113 {
114  NS_LOG_FUNCTION (this);
116  return 0;
117 }
118 int
120 {
121  return (-1);
122 }
123 int
125 {
126  address = InetSocketAddress (m_src, 0);
127  return 0;
128 }
129 int
131 {
132  NS_LOG_FUNCTION (this);
133  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
134  if (ipv4 != 0)
135  {
136  ipv4->DeleteRawSocket (this);
137  }
138  return 0;
139 }
140 int
142 {
143  NS_LOG_FUNCTION (this);
144  m_shutdownSend = true;
145  return 0;
146 }
147 int
149 {
150  NS_LOG_FUNCTION (this);
151  m_shutdownRecv = true;
152  return 0;
153 }
154 int
156 {
157  NS_LOG_FUNCTION (this << address);
158  if (!InetSocketAddress::IsMatchingType (address))
159  {
161  return -1;
162  }
164  m_dst = ad.GetIpv4 ();
165  return 0;
166 }
167 int
169 {
170  NS_LOG_FUNCTION (this);
172  return -1;
173 }
174 uint32_t
176 {
177  NS_LOG_FUNCTION (this);
178  return 0xffffffff;
179 }
180 int
182 {
183  NS_LOG_FUNCTION (this << p << flags);
185  return SendTo (p, flags, to);
186 }
187 int
189  const Address &toAddress)
190 {
191  NS_LOG_FUNCTION (this << p << flags << toAddress);
192  if (!InetSocketAddress::IsMatchingType (toAddress))
193  {
195  return -1;
196  }
197  if (m_shutdownSend)
198  {
199  return 0;
200  }
202  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
203  Ipv4Address dst = ad.GetIpv4 ();
204  Ipv4Address src = m_src;
205  if (ipv4->GetRoutingProtocol ())
206  {
207  Ipv4Header header;
208  if (!m_iphdrincl)
209  {
210  header.SetDestination (dst);
211  header.SetProtocol (m_protocol);
212  }
213  else
214  {
215  p->RemoveHeader (header);
216  dst = header.GetDestination ();
217  src = header.GetSource ();
218  }
219  SocketErrno errno_ = ERROR_NOTERROR; //do not use errno as it is the standard C last error number
220  Ptr<Ipv4Route> route;
221  Ptr<NetDevice> oif = m_boundnetdevice; //specify non-zero if bound to a source address
222  if (!oif && src != Ipv4Address::GetAny ())
223  {
224  int32_t index = ipv4->GetInterfaceForAddress (src);
225  NS_ASSERT (index >= 0);
226  oif = ipv4->GetNetDevice (index);
227  NS_LOG_LOGIC ("Set index " << oif << "from source " << src);
228  }
229 
230  // TBD-- we could cache the route and just check its validity
231  route = ipv4->GetRoutingProtocol ()->RouteOutput (p, header, oif, errno_);
232  if (route != 0)
233  {
234  NS_LOG_LOGIC ("Route exists");
235  if (!m_iphdrincl)
236  {
237  ipv4->Send (p, route->GetSource (), dst, m_protocol, route);
238  }
239  else
240  {
241  ipv4->SendWithHeader (p, header, route);
242  }
243  NotifyDataSent (p->GetSize ());
245  return p->GetSize ();
246  }
247  else
248  {
249  NS_LOG_DEBUG ("dropped because no outgoing route.");
250  return -1;
251  }
252  }
253  return 0;
254 }
255 uint32_t
257 {
258  NS_LOG_FUNCTION (this);
259  uint32_t rx = 0;
260  for (std::list<Data>::const_iterator i = m_recv.begin (); i != m_recv.end (); ++i)
261  {
262  rx += (i->packet)->GetSize ();
263  }
264  return rx;
265 }
267 Ipv4RawSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
268 {
269  NS_LOG_FUNCTION (this << maxSize << flags);
270  Address tmp;
271  return RecvFrom (maxSize, flags, tmp);
272 }
274 Ipv4RawSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags,
275  Address &fromAddress)
276 {
277  NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
278  if (m_recv.empty ())
279  {
280  return 0;
281  }
282  struct Data data = m_recv.front ();
283  m_recv.pop_front ();
285  fromAddress = inet;
286  if (data.packet->GetSize () > maxSize)
287  {
288  Ptr<Packet> first = data.packet->CreateFragment (0, maxSize);
289  if (!(flags & MSG_PEEK))
290  {
291  data.packet->RemoveAtStart (maxSize);
292  }
293  m_recv.push_front (data);
294  return first;
295  }
296  return data.packet;
297 }
298 
299 void
301 {
302  NS_LOG_FUNCTION (this << protocol);
303  m_protocol = protocol;
304 }
305 
306 bool
308 {
309  NS_LOG_FUNCTION (this << *p << ipHeader << incomingInterface);
310  if (m_shutdownRecv)
311  {
312  return false;
313  }
314  NS_LOG_LOGIC ("src = " << m_src << " dst = " << m_dst);
315  if ((m_src == Ipv4Address::GetAny () || ipHeader.GetDestination () == m_src) &&
316  (m_dst == Ipv4Address::GetAny () || ipHeader.GetSource () == m_dst) &&
317  ipHeader.GetProtocol () == m_protocol)
318  {
319  Ptr<Packet> copy = p->Copy ();
320  // Should check via getsockopt ()..
321  if (IsRecvPktInfo ())
322  {
323  Ipv4PacketInfoTag tag;
324  copy->RemovePacketTag (tag);
325  tag.SetRecvIf (incomingInterface->GetDevice ()->GetIfIndex ());
326  copy->AddPacketTag (tag);
327  }
328  if (m_protocol == 1)
329  {
330  Icmpv4Header icmpHeader;
331  copy->PeekHeader (icmpHeader);
332  uint8_t type = icmpHeader.GetType ();
333  if (type < 32 &&
334  ((uint32_t(1) << type) & m_icmpFilter))
335  {
336  // filter out icmp packet.
337  return false;
338  }
339  }
340  copy->AddHeader (ipHeader);
341  struct Data data;
342  data.packet = copy;
343  data.fromIp = ipHeader.GetSource ();
344  data.fromProtocol = ipHeader.GetProtocol ();
345  m_recv.push_back (data);
346  NotifyDataRecv ();
347  return true;
348  }
349  return false;
350 }
351 
352 bool
354 {
355  if (!allowBroadcast)
356  {
357  return false;
358  }
359  return true;
360 }
361 
362 bool
364 {
365  return true;
366 }
367 
368 } // namespace ns3