A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ipv6-raw-socket-impl.cc
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 {
61  m_err = Socket::ERROR_NOTERROR;
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 
93 enum Socket::SocketErrno Ipv6RawSocketImpl::GetErrno () const
94 {
96  return m_err;
97 }
98 
99 enum Socket::SocketType Ipv6RawSocketImpl::GetSocketType () const
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  {
110  m_err = Socket::ERROR_INVAL;
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  {
169  m_err = Socket::ERROR_INVAL;
170  return -1;
171  }
172 
174  m_dst = ad.GetIpv6 ();
175  return 0;
176 }
177 
179 {
181  m_err = Socket::ERROR_OPNOTSUPP;
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  {
198  m_err = Socket::ERROR_INVAL;
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);
215  SocketErrno err = ERROR_NOTERROR;
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));
238  if (type == Icmpv6Header::ICMPV6_ECHO_REQUEST)
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 
void SetNode(Ptr< Node > node)
Set the node.
bool IsAny() const
If the IPv6 address is the "Any" address.
uint32_t RemoveHeader(Header &header)
Definition: packet.cc:285
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
Definition: ipv6-header.cc:143
uint8_t GetNextHeader(void) const
Get the next header.
Definition: ipv6-header.cc:81
void CalculatePseudoHeaderChecksum(Ipv6Address src, Ipv6Address dst, uint16_t length, uint8_t protocol)
Calculate pseudo header checksum for IPv6.
Ipv6Address GetIpv6(void) const
Get the IPv6 address.
Packet header for IPv6.
Definition: ipv6-header.h:33
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
virtual void DoDispose()
Dispose object.
virtual int Connect(const Address &address)
Connect to address.
virtual uint32_t GetSerializedSize() const
Get the serialized size.
Ipv6Address m_src
Source address.
Ptr< Packet > Recv(void)
Read a single packet from the socket.
Definition: socket.cc:174
IPv6 layer implementation.
void AddPacketTag(const Tag &tag) const
Definition: packet.cc:868
bool m_shutdownSend
Flag to shutdown send capability.
uint8_t GetType() const
Get the type field.
#define NS_ASSERT(condition)
Definition: assert.h:64
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
uint32_t GetSize(void) const
Definition: packet.h:620
virtual int ShutdownSend()
Shutdown send capability.
#define NS_LOG_FUNCTION_NOARGS()
Definition: log.h:275
static TypeId GetTypeId()
Get the type ID of this class.
bool ForwardUp(Ptr< const Packet > p, Ipv6Header hdr, Ptr< NetDevice > device)
Forward up to receive method.
virtual enum Socket::SocketType GetSocketType() const
Get socket type (NS3_SOCK_RAW)
virtual enum Socket::SocketErrno GetErrno() const
Get last error number.
bool IsRecvPktInfo() const
Get status indicating whether enable/disable packet information to socket.
Definition: socket.cc:363
virtual int Send(Ptr< Packet > p, uint32_t flags)
Send a packet.
a polymophic address class
Definition: address.h:86
virtual int Bind()
Bind socket.
bool m_shutdownRecv
Flag to shutdown receive capability.
Ptr< NetDevice > GetBoundNetDevice()
Returns socket's bound netdevice, if any.
Definition: socket.cc:350
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Definition: packet.cc:243
A low-level Socket API based loosely on the BSD Socket API.A few things to keep in mind about this ty...
Definition: socket.h:66
ICMPv6 header.
Definition: icmpv6-header.h:37
void RemoveAtStart(uint32_t size)
Definition: packet.cc:370
std::list< struct Data > m_data
Packet waiting to be processed.
Hold an unsigned integer type.
Definition: uinteger.h:46
virtual int GetSockName(Address &address) const
Get socket address.
An Inet6 address class.
void Icmpv6FilterSetBlock(uint8_t type)
Set the filter to block one ICMPv6 type.
virtual int Bind6()
Allocate a local IPv6 endpoint for this socket.
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
virtual Ptr< Node > GetNode() const
Get node.
IPv6 raw data and additional information.
Struct to hold the ICMPv6 filter.
virtual int Listen()
Listen.
Ptr< Packet > Copy(void) const
Definition: packet.cc:131
uint32_t PeekHeader(Header &header) const
Definition: packet.cc:294
static uint16_t GetStaticProtocolNumber()
Get ICMPv6 protocol number.
bool Icmpv6FilterWillBlock(uint8_t type)
Ask the filter about the status of one ICMPv6 type.
void Icmpv6FilterSetPass(uint8_t type)
Set the filter to pass one ICMPv6 type.
virtual ~Ipv6RawSocketImpl()
Destructor.
icmpv6Filter m_icmpFilter
ICMPv6 filter.
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)
Receive packet.
virtual bool SetAllowBroadcast(bool allowBroadcast)
Configure whether broadcast datagram transmissions are allowed.
virtual void DoDispose(void)
Definition: socket.cc:314
ICMPv6 Echo message.
virtual uint32_t GetRxAvailable() const
Get RX size available.
Describes an IPv6 address.
Definition: ipv6-address.h:44
virtual uint32_t GetTxAvailable() const
Get TX size available.
enum Socket::SocketErrno m_err
Last error number.
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)
Send a packet.
virtual int Close()
Close the socket.
Ipv6Address m_dst
Destination address.
bool RemovePacketTag(Tag &tag)
Definition: packet.cc:874
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:101
#define NS_LOG_DEBUG(msg)
Definition: log.h:255
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
bool Icmpv6FilterWillPass(uint8_t type)
Ask the filter about the status of one ICMPv6 type.
void Icmpv6FilterSetPassAll()
Clean the ICMPv6 filter structure.
static bool IsMatchingType(const Address &addr)
If the address match.
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Definition: packet.cc:398
This class implements a tag that carries socket ancillary data to the socket interface. This is used like socket option of IP_PKTINFO/IPV6_PKTINFO in RFC 3542 See: http://tools.ietf.org/html/rfc3542.
virtual int ShutdownRecv()
Shutdown receive capability.
Ptr< T > GetObject(void) const
Definition: object.h:332
virtual bool GetAllowBroadcast() const
Query whether broadcast datagram transmissions are allowed.
a unique identifier for an interface.
Definition: type-id.h:44
void SetDestinationAddress(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:106
TypeId SetParent(TypeId tid)
Definition: type-id.cc:471
void AddHeader(const Header &header)
Definition: packet.cc:270
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:111
uint16_t m_protocol
Protocol.
void Icmpv6FilterSetBlockAll()
Set the filter to block all the ICMPv6 types.