A Discrete-Event Network Simulator
API
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 NS_OBJECT_ENSURE_REGISTERED (Ipv6RawSocketImpl);
44 
46 {
47  static TypeId tid = TypeId ("ns3::Ipv6RawSocketImpl")
48  .SetParent<Socket> ()
49  .SetGroupName ("Internet")
50  .AddAttribute ("Protocol", "Protocol number to match.",
51  UintegerValue (0),
53  MakeUintegerChecker<uint16_t> ())
54  ;
55  return tid;
56 }
57 
59 {
60  NS_LOG_FUNCTION (this);
62  m_node = 0;
65  m_protocol = 0;
66  m_shutdownSend = false;
67  m_shutdownRecv = false;
69 }
70 
72 {
73 }
74 
76 {
77  NS_LOG_FUNCTION (this);
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 {
95  NS_LOG_FUNCTION (this);
96  return m_err;
97 }
98 
100 {
101  return NS3_SOCK_RAW;
102 }
103 
105 {
106  NS_LOG_FUNCTION (this << address);
107 
109  {
111  return -1;
112  }
114  m_src = ad.GetIpv6 ();
115  return 0;
116 }
117 
119 {
120  NS_LOG_FUNCTION (this);
122  return 0;
123 }
124 
126 {
127  return(Bind());
128 }
129 
131 {
132  NS_LOG_FUNCTION (this);
134  return 0;
135 }
136 
137 int
139 {
140  NS_LOG_FUNCTION (this << address);
141 
142  if (m_dst.IsAny ())
143  {
145  return -1;
146  }
147 
149 
150  return 0;
151 }
152 
154 {
155  NS_LOG_FUNCTION (this);
157 
158  Ipv6LeaveGroup ();
159  if (ipv6)
160  {
161  ipv6->DeleteRawSocket (this);
162  }
163  return 0;
164 }
165 
167 {
168  NS_LOG_FUNCTION (this);
169  m_shutdownSend = true;
170  return 0;
171 }
172 
174 {
175  NS_LOG_FUNCTION (this);
176  m_shutdownRecv = true;
177  return 0;
178 }
179 
181 {
182  NS_LOG_FUNCTION (this << address);
183 
185  {
187  return -1;
188  }
190  m_dst = ad.GetIpv6 ();
191 
192  return 0;
193 }
194 
196 {
197  NS_LOG_FUNCTION (this);
199  return -1;
200 }
201 
202 int Ipv6RawSocketImpl::Send (Ptr<Packet> p, uint32_t flags)
203 {
204  NS_LOG_FUNCTION (this << p << flags);
206  return SendTo (p, flags, to);
207 }
208 
209 int Ipv6RawSocketImpl::SendTo (Ptr<Packet> p, uint32_t flags, const Address& toAddress)
210 {
211  NS_LOG_FUNCTION (this << p << flags << toAddress);
212 
213  if (!Inet6SocketAddress::IsMatchingType (toAddress))
214  {
216  return -1;
217  }
218 
219  if (m_shutdownSend)
220  {
221  return 0;
222  }
223 
226  Ipv6Address dst = ad.GetIpv6 ();
227 
228  if (IsManualIpv6Tclass ())
229  {
230  SocketIpv6TclassTag ipTclassTag;
231  ipTclassTag.SetTclass (GetIpv6Tclass ());
232  p->AddPacketTag (ipTclassTag);
233  }
234 
235  if (IsManualIpv6HopLimit () && GetIpv6HopLimit () != 0 && !dst.IsMulticast ())
236  {
238  tag.SetHopLimit (GetIpv6HopLimit ());
239  p->AddPacketTag (tag);
240  }
241 
242  if (ipv6->GetRoutingProtocol ())
243  {
244  Ipv6Header hdr;
245  hdr.SetDestinationAddress (dst);
247  Ptr<Ipv6Route> route = 0;
248  Ptr<NetDevice> oif = m_boundnetdevice; //specify non-zero if bound to a specific device
249 
250  if (!m_src.IsAny ())
251  {
252  int32_t index = ipv6->GetInterfaceForAddress (m_src);
253  NS_ASSERT (index >= 0);
254  oif = ipv6->GetNetDevice (index);
255  }
256 
257  route = ipv6->GetRoutingProtocol ()->RouteOutput (p, hdr, oif, err);
258 
259  if (route)
260  {
261  NS_LOG_LOGIC ("Route exists");
263  {
264  /* calculate checksum here for ICMPv6 echo request (sent by ping6)
265  * as we cannot determine source IPv6 address at application level
266  */
267  uint8_t type;
268  p->CopyData (&type, sizeof(type));
270  {
271  Icmpv6Echo hdr (1);
272  p->RemoveHeader (hdr);
274  p->AddHeader (hdr);
275  }
276  }
277 
278  uint32_t pktSize = p->GetSize ();
279  if (m_src.IsAny ())
280  {
281  ipv6->Send (p, route->GetSource (), dst, m_protocol, route);
282  }
283  else
284  {
285  ipv6->Send (p, m_src, dst, m_protocol, route);
286  }
287  // Return only payload size (as Linux does).
290  return pktSize;
291  }
292  else
293  {
294  NS_LOG_DEBUG ("No route, dropped!");
295  }
296  }
297  return 0;
298 }
299 
300 Ptr<Packet> Ipv6RawSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
301 {
302  NS_LOG_FUNCTION (this << maxSize << flags);
303  Address tmp;
304  return RecvFrom (maxSize, flags, tmp);
305 }
306 
307 Ptr<Packet> Ipv6RawSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags, Address& fromAddress)
308 {
309  NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
310 
311  if (m_data.empty ())
312  {
313  return 0;
314  }
315 
316  /* get packet */
317  Data data = m_data.front ();
318  m_data.pop_front ();
319  fromAddress = Inet6SocketAddress (data.fromIp, data.fromProtocol);
320  if (data.packet->GetSize () > maxSize)
321  {
322  Ptr<Packet> first = data.packet->CreateFragment (0, maxSize);
323  if (!(flags & MSG_PEEK))
324  {
325  data.packet->RemoveAtStart (maxSize);
326  }
327  m_data.push_front (data);
328  return first;
329  }
330 
331  return data.packet;
332 }
333 
334 void
335 Ipv6RawSocketImpl::Ipv6JoinGroup (Ipv6Address address, Socket::Ipv6MulticastFilterMode filterMode, std::vector<Ipv6Address> sourceAddresses)
336 {
337  NS_LOG_FUNCTION (this << address << &filterMode << &sourceAddresses);
338 
339  // We can join only one multicast group (or change its params)
340  NS_ASSERT_MSG ((m_ipv6MulticastGroupAddress == address || m_ipv6MulticastGroupAddress.IsAny ()), "Can join only one IPv6 multicast group.");
341 
343 
345  if (ipv6l3)
346  {
347  if (filterMode == INCLUDE && sourceAddresses.empty ())
348  {
349  // it is a leave
350  if (m_boundnetdevice)
351  {
352  int32_t index = ipv6l3->GetInterfaceForDevice (m_boundnetdevice);
353  NS_ASSERT_MSG (index >= 0, "Interface without a valid index");
354  ipv6l3->RemoveMulticastAddress (address, index);
355  }
356  else
357  {
358  ipv6l3->RemoveMulticastAddress (address);
359  }
360  }
361  else
362  {
363  // it is a join or a modification
364  if (m_boundnetdevice)
365  {
366  int32_t index = ipv6l3->GetInterfaceForDevice (m_boundnetdevice);
367  NS_ASSERT_MSG (index >= 0, "Interface without a valid index");
368  ipv6l3->AddMulticastAddress (address, index);
369  }
370  else
371  {
372  ipv6l3->AddMulticastAddress (address);
373  }
374  }
375  }
376 }
377 
379 {
380  NS_LOG_FUNCTION (this);
381  return 0xffffffff;
382 }
383 
385 {
386  NS_LOG_FUNCTION (this);
387  uint32_t rx = 0;
388 
389  for (std::list<Data>::const_iterator it = m_data.begin (); it != m_data.end (); ++it)
390  {
391  rx+= (it->packet)->GetSize ();
392  }
393 
394  return rx;
395 }
396 
398 {
399  NS_LOG_FUNCTION (this << *p << hdr << device);
400 
401  if (m_shutdownRecv)
402  {
403  return false;
404  }
405 
406  Ptr<NetDevice> boundNetDevice = Socket::GetBoundNetDevice();
407  if (boundNetDevice)
408  {
409  if (boundNetDevice != device)
410  {
411  return false;
412  }
413  }
414 
415  if ((m_src == Ipv6Address::GetAny () || hdr.GetDestinationAddress () == m_src) &&
416  (m_dst == Ipv6Address::GetAny () || hdr.GetSourceAddress () == m_dst) &&
417  hdr.GetNextHeader () == m_protocol)
418  {
419  Ptr<Packet> copy = p->Copy ();
420 
422  {
423  /* filter */
424  Icmpv6Header icmpHeader;
425  copy->PeekHeader (icmpHeader);
426  uint8_t type = icmpHeader.GetType ();
427 
428  if (Icmpv6FilterWillBlock(type))
429  {
430  /* packet filtered */
431  return false;
432  }
433  }
434 
435  // Should check via getsockopt ().
436  if (IsRecvPktInfo ())
437  {
438  Ipv6PacketInfoTag tag;
439  copy->RemovePacketTag (tag);
440  tag.SetAddress (hdr.GetDestinationAddress ());
441  tag.SetHoplimit (hdr.GetHopLimit ());
442  tag.SetTrafficClass (hdr.GetTrafficClass ());
443  tag.SetRecvIf (device->GetIfIndex ());
444  copy->AddPacketTag (tag);
445  }
446 
447  // Check only version 6 options
448  if (IsIpv6RecvTclass ())
449  {
450  SocketIpv6TclassTag ipTclassTag;
451  ipTclassTag.SetTclass (hdr.GetTrafficClass ());
452  copy->AddPacketTag (ipTclassTag);
453  }
454 
455  if (IsIpv6RecvHopLimit ())
456  {
457  SocketIpv6HopLimitTag ipHopLimitTag;
458  ipHopLimitTag.SetHopLimit (hdr.GetHopLimit ());
459  copy->AddPacketTag (ipHopLimitTag);
460  }
461 
462  copy->AddHeader (hdr);
463  Data data;
464  data.packet = copy;
465  data.fromIp = hdr.GetSourceAddress ();
466  data.fromProtocol = hdr.GetNextHeader ();
467  m_data.push_back (data);
468  NotifyDataRecv ();
469  return true;
470  }
471  return false;
472 }
473 
474 bool
476 {
477  if (!allowBroadcast)
478  {
479  return false;
480  }
481  return true;
482 }
483 
484 bool
486 {
487  return true;
488 }
489 
490 void
492 {
493  memset(&m_icmpFilter, 0xff, sizeof(Icmpv6Filter));
494 }
495 
496 void
498 {
499  memset(&m_icmpFilter, 0x00, sizeof(Icmpv6Filter));
500 }
501 
502 void
504 {
505  (m_icmpFilter.icmpv6Filt[(type) >> 5]) |= (uint32_t(1) << ((type) & 31));
506 }
507 
508 void
510 {
511  (m_icmpFilter.icmpv6Filt[(type) >> 5]) &= ~(uint32_t(1) << ((type) & 31));
512 }
513 
514 bool
516 {
517  return (((m_icmpFilter.icmpv6Filt[(type) >> 5]) & (uint32_t(1) << ((type) & 31))) != 0);
518 }
519 
520 bool
522 {
523  return (((m_icmpFilter.icmpv6Filt[(type) >> 5]) & (uint32_t(1) << ((type) & 31))) == 0);
524 }
525 
526 } /* namespace ns3 */
527 
void SetNode(Ptr< Node > node)
Set the node associated with this socket.
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void SetTclass(uint8_t tclass)
Set the tag&#39;s Tclass.
Definition: socket.cc:900
void CalculatePseudoHeaderChecksum(Ipv6Address src, Ipv6Address dst, uint16_t length, uint8_t protocol)
Calculate pseudo header checksum for IPv6.
void SetAddress(Ipv6Address addr)
Set the tag&#39;s address.
Packet header for IPv6.
Definition: ipv6-header.h:34
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void SetTrafficClass(uint8_t tclass)
Set the tag&#39;s Traffic Class.
virtual void Ipv6JoinGroup(Ipv6Address address, Socket::Ipv6MulticastFilterMode filterMode, std::vector< Ipv6Address > sourceAddresses)
Joins a IPv6 multicast group.
virtual void DoDispose()
Dispose object.
This class implements a tag that carries the socket-specific HOPLIMIT of a packet to the IPv6 layer...
Definition: socket.h:1163
virtual int Connect(const Address &address)
Initiate a connection to a remote host.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
Ipv6Address GetIpv6(void) const
Get the IPv6 address.
void NotifyDataRecv(void)
Notify through the callback (if set) that some data have been received.
Definition: socket.cc:305
Ipv6Address m_src
Source address.
Ptr< Packet > Recv(void)
Read a single packet from the socket.
Definition: socket.cc:175
IPv6 layer implementation.
Icmpv6Filter m_icmpFilter
ICMPv6 filter.
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:238
bool m_shutdownSend
Flag to shutdown send capability.
std::list< Data > m_data
Packet waiting to be processed.
#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
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
virtual uint32_t GetSerializedSize() const
Get the serialized size.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
virtual enum Socket::SocketType GetSocketType() const
Get socket type (NS3_SOCK_RAW)
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.
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
Ipv6Address m_ipv6MulticastGroupAddress
IPv6 multicast group address.
Definition: socket.h:1078
virtual Ptr< Node > GetNode() const
Return the node this socket is associated with.
virtual int Send(Ptr< Packet > p, uint32_t flags)
Send data (or dummy data) to the remote host.
a polymophic address class
Definition: address.h:90
uint32_t icmpv6Filt[8]
ICMPv6 filter specification.
virtual int Bind()
Allocate a local IPv4 endpoint for this socket.
bool m_shutdownRecv
Flag to shutdown receive capability.
Ptr< NetDevice > GetBoundNetDevice()
Returns socket&#39;s bound NetDevice, if any.
Definition: socket.cc:351
A low-level Socket API based loosely on the BSD Socket API.
Definition: socket.h:66
ICMPv6 header.
Definition: icmpv6-header.h:38
Ipv6MulticastFilterMode
Enumeration of the possible filter of a socket.
Definition: socket.h:138
Struct to hold the ICMPv6 filter.
Hold an unsigned integer type.
Definition: uinteger.h:44
uint8_t data[writeSize]
void SetHoplimit(uint8_t ttl)
Set the tag&#39;s Hop Limit.
bool IsIpv6RecvTclass(void) const
Ask if the socket is currently passing information about IPv6 Traffic Class up the stack...
Definition: socket.cc:507
An Inet6 address class.
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
void NotifyDataSent(uint32_t size)
Notify through the callback (if set) that some data have been sent.
Definition: socket.cc:285
void Icmpv6FilterSetBlock(uint8_t type)
Set the filter to block one ICMPv6 type.
virtual int Bind6()
Allocate a local IPv6 endpoint for this socket.
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:100
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
void SetHopLimit(uint8_t hopLimit)
Set the tag&#39;s Hop Limit.
Definition: socket.cc:665
IPv6 raw data and additional information.
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
virtual int Listen()
Listen for incoming connections.
virtual uint32_t GetRxAvailable() const
Return number of bytes which can be returned from one or multiple calls to Recv.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
address
Definition: first.py:44
static uint16_t GetStaticProtocolNumber()
Get ICMPv6 protocol number.
bool IsManualIpv6Tclass(void) const
Checks if the socket has a specific IPv6 Tclass set.
Definition: socket.cc:371
bool Icmpv6FilterWillBlock(uint8_t type)
Ask the filter about the status of one ICMPv6 type.
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
indicates whether the socket has IPV6_TCLASS set.
Definition: socket.h:1354
virtual void Ipv6LeaveGroup(void)
Leaves IPv6 multicast group this socket is joined to.
Definition: socket.cc:580
uint8_t GetNextHeader(void) const
Get the next header.
Definition: ipv6-header.cc:80
void Icmpv6FilterSetPass(uint8_t type)
Set the filter to pass one ICMPv6 type.
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 bool SetAllowBroadcast(bool allowBroadcast)
Configure whether broadcast datagram transmissions are allowed.
uint8_t GetIpv6Tclass(void) const
Query the value of IPv6 Traffic Class field of this socket.
Definition: socket.cc:495
virtual void DoDispose(void)
Destructor implementation.
Definition: socket.cc:315
ICMPv6 Echo message.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
virtual bool GetAllowBroadcast() const
Query whether broadcast datagram transmissions are allowed.
bool IsManualIpv6HopLimit(void) const
Checks if the socket has a specific IPv6 Hop Limit set.
Definition: socket.cc:383
virtual int GetPeerName(Address &address) const
Get the peer address of a connected socket.
Describes an IPv6 address.
Definition: ipv6-address.h:49
enum Socket::SocketErrno m_err
Last error number.
virtual int GetSockName(Address &address) const
Get socket address.
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)
Send data to a specified peer.
Ptr< NetDevice > m_boundnetdevice
the device this socket is bound to (might be null).
Definition: socket.h:1076
uint8_t GetTrafficClass(void) const
Get the "Traffic class" field.
Definition: ipv6-header.cc:50
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
virtual uint8_t GetIpv6HopLimit(void) const
Query the value of IP Hop Limit field of this socket.
Definition: socket.cc:545
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
virtual int Close()
Close a socket.
virtual enum Socket::SocketErrno GetErrno() const
Get last error number.
Ipv6Address m_dst
Destination address.
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:963
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
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.
bool IsIpv6RecvHopLimit(void) const
Ask if the socket is currently passing information about IPv6 Hop Limit up the stack.
Definition: socket.cc:557
virtual uint32_t GetTxAvailable() const
Returns the number of bytes which can be sent in a single call to Send.
static bool IsMatchingType(const Address &addr)
If the address match.
bool IsRecvPktInfo() const
Get status indicating whether enable/disable packet information to socket.
Definition: socket.cc:364
This class implements a tag that carries socket ancillary data to the socket interface.
uint8_t GetType() const
Get the type field.
uint8_t GetHopLimit(void) const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:90
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:110
Definition: first.py:1
uint32_t pktSize
packet size used for the simulation (in bytes)
Definition: wifi-bianchi.cc:83
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
SocketType
Enumeration of the possible socket types.
Definition: socket.h:104
a unique identifier for an interface.
Definition: type-id.h:58
void SetDestinationAddress(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:105
void NotifySend(uint32_t spaceAvailable)
Notify through the callback (if set) that some data have been sent.
Definition: socket.cc:295
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
void SetRecvIf(uint32_t ifindex)
Set the tag&#39;s receiving interface.
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
uint16_t m_protocol
Protocol.
bool IsAny() const
If the IPv6 address is the "Any" address.
void Icmpv6FilterSetBlockAll()
Set the filter to block all the ICMPv6 types.