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  }
249  else
250  {
251  NS_LOG_DEBUG ("No route, dropped!");
252  }
253  }
254  return 0;
255 }
256 
257 Ptr<Packet> Ipv6RawSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
258 {
259  NS_LOG_FUNCTION (this << maxSize << flags);
260  Address tmp;
261  return RecvFrom (maxSize, flags, tmp);
262 }
263 
264 Ptr<Packet> Ipv6RawSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags, Address& fromAddress)
265 {
266  NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
267 
268  if (m_data.empty ())
269  {
270  return 0;
271  }
272 
273  /* get packet */
274  struct Data data = m_data.front ();
275  m_data.pop_front ();
276 
277  if (data.packet->GetSize () > maxSize)
278  {
279  Ptr<Packet> first = data.packet->CreateFragment (0, maxSize);
280  if (!(flags & MSG_PEEK))
281  {
282  data.packet->RemoveAtStart (maxSize);
283  }
284  m_data.push_front (data);
285  return first;
286  }
287 
288  fromAddress = Inet6SocketAddress (data.fromIp, data.fromProtocol);
289  return data.packet;
290 }
291 
293 {
295  return 0xffffffff;
296 }
297 
299 {
301  uint32_t rx = 0;
302 
303  for (std::list<Data>::const_iterator it = m_data.begin (); it != m_data.end (); ++it)
304  {
305  rx+= (it->packet)->GetSize ();
306  }
307 
308  return rx;
309 }
310 
312 {
313  NS_LOG_FUNCTION (this << *p << hdr << device);
314 
315  if (m_shutdownRecv)
316  {
317  return false;
318  }
319 
320  Ptr<NetDevice> boundNetDevice = Socket::GetBoundNetDevice();
321  if (boundNetDevice)
322  {
323  if (boundNetDevice != device)
324  {
325  return false;
326  }
327  }
328 
329  if ((m_src == Ipv6Address::GetAny () || hdr.GetDestinationAddress () == m_src) &&
330  (m_dst == Ipv6Address::GetAny () || hdr.GetSourceAddress () == m_dst) &&
331  hdr.GetNextHeader () == m_protocol)
332  {
333  Ptr<Packet> copy = p->Copy ();
334 
336  {
337  /* filter */
338  Icmpv6Header icmpHeader;
339  copy->PeekHeader (icmpHeader);
340  uint8_t type = icmpHeader.GetType ();
341 
342  if (Icmpv6FilterWillBlock(type))
343  {
344  /* packet filtered */
345  return false;
346  }
347  }
348 
349  // Should check via getsockopt ()..
350  if (IsRecvPktInfo ())
351  {
352  Ipv6PacketInfoTag tag;
353  copy->RemovePacketTag (tag);
354  tag.SetRecvIf (device->GetIfIndex ());
355  copy->AddPacketTag (tag);
356  }
357 
358  copy->AddHeader (hdr);
359  struct Data data;
360  data.packet = copy;
361  data.fromIp = hdr.GetSourceAddress ();
362  data.fromProtocol = hdr.GetNextHeader ();
363  m_data.push_back (data);
364  NotifyDataRecv ();
365  return true;
366  }
367  return false;
368 }
369 
370 bool
372 {
373  if (!allowBroadcast)
374  {
375  return false;
376  }
377  return true;
378 }
379 
380 bool
382 {
383  return true;
384 }
385 
386 void
388 {
389  memset(&m_icmpFilter, 0xff, sizeof(icmpv6Filter));
390 }
391 
392 void
394 {
395  memset(&m_icmpFilter, 0x00, sizeof(icmpv6Filter));
396 }
397 
398 void
400 {
401  (m_icmpFilter.icmpv6Filt[(type) >> 5]) |= (uint32_t(1) << ((type) & 31));
402 }
403 
404 void
406 {
407  (m_icmpFilter.icmpv6Filt[(type) >> 5]) &= ~(uint32_t(1) << ((type) & 31));
408 }
409 
410 bool
412 {
413  return (((m_icmpFilter.icmpv6Filt[(type) >> 5]) & (uint32_t(1) << ((type) & 31))) != 0);
414 }
415 
416 bool
418 {
419  return (((m_icmpFilter.icmpv6Filt[(type) >> 5]) & (uint32_t(1) << ((type) & 31))) == 0);
420 }
421 
422 } /* namespace ns3 */
423