A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ipv6-raw-socket-impl.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007-2009 Strasbourg University
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
19  */
20 
21 #include <netinet/in.h>
22 #include <sys/socket.h>
23 #include <sys/types.h>
24 #include "ns3/inet6-socket-address.h"
25 #include "ns3/node.h"
26 #include "ns3/packet.h"
27 #include "ns3/uinteger.h"
28 #include "ns3/log.h"
29 #include "ns3/ipv6-route.h"
30 #include "ns3/ipv6-routing-protocol.h"
31 #include "ns3/ipv6-packet-info-tag.h"
32 
33 #include "ipv6-l3-protocol.h"
34 #include "ipv6-raw-socket-impl.h"
35 #include "icmpv6-header.h"
36 #include "icmpv6-l4-protocol.h"
37 
38 namespace ns3
39 {
40 
41 NS_LOG_COMPONENT_DEFINE ("Ipv6RawSocketImpl");
42 
43 
44 NS_OBJECT_ENSURE_REGISTERED (Ipv6RawSocketImpl);
45 
47 {
48  static TypeId tid = TypeId ("ns3::Ipv6RawSocketImpl")
49  .SetParent<Socket> ()
50  .AddAttribute ("Protocol", "Protocol number to match.",
51  UintegerValue (0),
52  MakeUintegerAccessor (&Ipv6RawSocketImpl::m_protocol),
53  MakeUintegerChecker<uint16_t> ())
54  ;
55  return tid;
56 }
57 
59 {
62  m_node = 0;
65  m_protocol = 0;
66  m_shutdownSend = false;
67  m_shutdownRecv = false;
69 }
70 
72 {
73 }
74 
76 {
78  m_node = 0;
80 }
81 
83 {
84  NS_LOG_FUNCTION (this << node);
85  m_node = node;
86 }
87 
89 {
90  return m_node;
91 }
92 
94 {
96  return m_err;
97 }
98 
100 {
101  return NS3_SOCK_RAW;
102 }
103 
104 int Ipv6RawSocketImpl::Bind (const Address& address)
105 {
106  NS_LOG_FUNCTION (this << address);
107 
108  if (!Inet6SocketAddress::IsMatchingType (address))
109  {
111  return -1;
112  }
114  m_src = ad.GetIpv6 ();
115  return 0;
116 }
117 
119 {
122  return 0;
123 }
124 
126 {
127  return(Bind());
128 }
129 
131 {
133  address = Inet6SocketAddress (m_src, 0);
134  return 0;
135 }
136 
138 {
141 
142  if (ipv6)
143  {
144  ipv6->DeleteRawSocket (this);
145  }
146  return 0;
147 }
148 
150 {
152  m_shutdownSend = true;
153  return 0;
154 }
155 
157 {
159  m_shutdownRecv = true;
160  return 0;
161 }
162 
164 {
165  NS_LOG_FUNCTION (this << address);
166 
167  if (!Inet6SocketAddress::IsMatchingType (address))
168  {
170  return -1;
171  }
172 
174  m_dst = ad.GetIpv6 ();
175  return 0;
176 }
177 
179 {
182  return -1;
183 }
184 
185 int Ipv6RawSocketImpl::Send (Ptr<Packet> p, uint32_t flags)
186 {
187  NS_LOG_FUNCTION (this << p << flags);
189  return SendTo (p, flags, to);
190 }
191 
192 int Ipv6RawSocketImpl::SendTo (Ptr<Packet> p, uint32_t flags, const Address& toAddress)
193 {
194  NS_LOG_FUNCTION (this << p << flags << toAddress);
195 
196  if (!Inet6SocketAddress::IsMatchingType (toAddress))
197  {
199  return -1;
200  }
201 
202  if (m_shutdownSend)
203  {
204  return 0;
205  }
206 
209  Ipv6Address dst = ad.GetIpv6 ();
210 
211  if (ipv6->GetRoutingProtocol ())
212  {
213  Ipv6Header hdr;
214  hdr.SetDestinationAddress (dst);
216  Ptr<Ipv6Route> route = 0;
217  Ptr<NetDevice> oif (0); /*specify non-zero if bound to a source address */
218 
219  if (!m_src.IsAny ())
220  {
221  int32_t index = ipv6->GetInterfaceForAddress (m_src);
222  NS_ASSERT (index >= 0);
223  oif = ipv6->GetNetDevice (index);
224  }
225 
226  route = ipv6->GetRoutingProtocol ()->RouteOutput (p, hdr, oif, err);
227 
228  if (route)
229  {
230  NS_LOG_LOGIC ("Route exists");
232  {
233  /* calculate checksum here for ICMPv6 echo request (sent by ping6)
234  * as we cannot determine source IPv6 address at application level
235  */
236  uint8_t type;
237  p->CopyData (&type, sizeof(type));
239  {
240  Icmpv6Echo hdr (1);
241  p->RemoveHeader (hdr);
243  p->AddHeader (hdr);
244  }
245  }
246 
247  ipv6->Send (p, route->GetSource (), dst, m_protocol, route);
248  // Return only payload size (as Linux does).
249  return p->GetSize () - hdr.GetSerializedSize ();
250  }
251  else
252  {
253  NS_LOG_DEBUG ("No route, dropped!");
254  }
255  }
256  return 0;
257 }
258 
259 Ptr<Packet> Ipv6RawSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
260 {
261  NS_LOG_FUNCTION (this << maxSize << flags);
262  Address tmp;
263  return RecvFrom (maxSize, flags, tmp);
264 }
265 
266 Ptr<Packet> Ipv6RawSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags, Address& fromAddress)
267 {
268  NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
269 
270  if (m_data.empty ())
271  {
272  return 0;
273  }
274 
275  /* get packet */
276  struct Data data = m_data.front ();
277  m_data.pop_front ();
278  fromAddress = Inet6SocketAddress (data.fromIp, data.fromProtocol);
279  if (data.packet->GetSize () > maxSize)
280  {
281  Ptr<Packet> first = data.packet->CreateFragment (0, maxSize);
282  if (!(flags & MSG_PEEK))
283  {
284  data.packet->RemoveAtStart (maxSize);
285  }
286  m_data.push_front (data);
287  return first;
288  }
289 
290  return data.packet;
291 }
292 
294 {
296  return 0xffffffff;
297 }
298 
300 {
302  uint32_t rx = 0;
303 
304  for (std::list<Data>::const_iterator it = m_data.begin (); it != m_data.end (); ++it)
305  {
306  rx+= (it->packet)->GetSize ();
307  }
308 
309  return rx;
310 }
311 
313 {
314  NS_LOG_FUNCTION (this << *p << hdr << device);
315 
316  if (m_shutdownRecv)
317  {
318  return false;
319  }
320 
321  Ptr<NetDevice> boundNetDevice = Socket::GetBoundNetDevice();
322  if (boundNetDevice)
323  {
324  if (boundNetDevice != device)
325  {
326  return false;
327  }
328  }
329 
330  if ((m_src == Ipv6Address::GetAny () || hdr.GetDestinationAddress () == m_src) &&
331  (m_dst == Ipv6Address::GetAny () || hdr.GetSourceAddress () == m_dst) &&
332  hdr.GetNextHeader () == m_protocol)
333  {
334  Ptr<Packet> copy = p->Copy ();
335 
337  {
338  /* filter */
339  Icmpv6Header icmpHeader;
340  copy->PeekHeader (icmpHeader);
341  uint8_t type = icmpHeader.GetType ();
342 
343  if (Icmpv6FilterWillBlock(type))
344  {
345  /* packet filtered */
346  return false;
347  }
348  }
349 
350  // Should check via getsockopt ()..
351  if (IsRecvPktInfo ())
352  {
353  Ipv6PacketInfoTag tag;
354  copy->RemovePacketTag (tag);
355  tag.SetRecvIf (device->GetIfIndex ());
356  copy->AddPacketTag (tag);
357  }
358 
359  copy->AddHeader (hdr);
360  struct Data data;
361  data.packet = copy;
362  data.fromIp = hdr.GetSourceAddress ();
363  data.fromProtocol = hdr.GetNextHeader ();
364  m_data.push_back (data);
365  NotifyDataRecv ();
366  return true;
367  }
368  return false;
369 }
370 
371 bool
373 {
374  if (!allowBroadcast)
375  {
376  return false;
377  }
378  return true;
379 }
380 
381 bool
383 {
384  return true;
385 }
386 
387 void
389 {
390  memset(&m_icmpFilter, 0xff, sizeof(icmpv6Filter));
391 }
392 
393 void
395 {
396  memset(&m_icmpFilter, 0x00, sizeof(icmpv6Filter));
397 }
398 
399 void
401 {
402  (m_icmpFilter.icmpv6Filt[(type) >> 5]) |= (uint32_t(1) << ((type) & 31));
403 }
404 
405 void
407 {
408  (m_icmpFilter.icmpv6Filt[(type) >> 5]) &= ~(uint32_t(1) << ((type) & 31));
409 }
410 
411 bool
413 {
414  return (((m_icmpFilter.icmpv6Filt[(type) >> 5]) & (uint32_t(1) << ((type) & 31))) != 0);
415 }
416 
417 bool
419 {
420  return (((m_icmpFilter.icmpv6Filt[(type) >> 5]) & (uint32_t(1) << ((type) & 31))) == 0);
421 }
422 
423 } /* namespace ns3 */
424