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 {
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 
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 
137 int
139 {
140  NS_LOG_FUNCTION (this << address);
141 
142  if (m_dst.IsAny ())
143  {
145  return -1;
146  }
147 
148  address = Inet6SocketAddress (m_dst, 0);
149 
150  return 0;
151 }
152 
154 {
157 
158  Ipv6LeaveGroup ();
159  if (ipv6)
160  {
161  ipv6->DeleteRawSocket (this);
162  }
163  return 0;
164 }
165 
167 {
169  m_shutdownSend = true;
170  return 0;
171 }
172 
174 {
176  m_shutdownRecv = true;
177  return 0;
178 }
179 
181 {
182  NS_LOG_FUNCTION (this << address);
183 
184  if (!Inet6SocketAddress::IsMatchingType (address))
185  {
187  return -1;
188  }
190  m_dst = ad.GetIpv6 ();
191 
192  return 0;
193 }
194 
196 {
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 (0); /*specify non-zero if bound to a source address */
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).
288  NotifyDataSent (pktSize);
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 {
381  return 0xffffffff;
382 }
383 
385 {
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.SetRecvIf (device->GetIfIndex ());
441  copy->AddPacketTag (tag);
442  }
443 
444  // Check only version 6 options
445  if (IsIpv6RecvTclass ())
446  {
447  SocketIpv6TclassTag ipTclassTag;
448  ipTclassTag.SetTclass (hdr.GetTrafficClass ());
449  copy->AddPacketTag (ipTclassTag);
450  }
451 
452  if (IsIpv6RecvHopLimit ())
453  {
454  SocketIpv6HopLimitTag ipHopLimitTag;
455  ipHopLimitTag.SetHopLimit (hdr.GetHopLimit ());
456  copy->AddPacketTag (ipHopLimitTag);
457  }
458 
459  copy->AddHeader (hdr);
460  Data data;
461  data.packet = copy;
462  data.fromIp = hdr.GetSourceAddress ();
463  data.fromProtocol = hdr.GetNextHeader ();
464  m_data.push_back (data);
465  NotifyDataRecv ();
466  return true;
467  }
468  return false;
469 }
470 
471 bool
473 {
474  if (!allowBroadcast)
475  {
476  return false;
477  }
478  return true;
479 }
480 
481 bool
483 {
484  return true;
485 }
486 
487 void
489 {
490  memset(&m_icmpFilter, 0xff, sizeof(Icmpv6Filter));
491 }
492 
493 void
495 {
496  memset(&m_icmpFilter, 0x00, sizeof(Icmpv6Filter));
497 }
498 
499 void
501 {
502  (m_icmpFilter.icmpv6Filt[(type) >> 5]) |= (uint32_t(1) << ((type) & 31));
503 }
504 
505 void
507 {
508  (m_icmpFilter.icmpv6Filt[(type) >> 5]) &= ~(uint32_t(1) << ((type) & 31));
509 }
510 
511 bool
513 {
514  return (((m_icmpFilter.icmpv6Filt[(type) >> 5]) & (uint32_t(1) << ((type) & 31))) != 0);
515 }
516 
517 bool
519 {
520  return (((m_icmpFilter.icmpv6Filt[(type) >> 5]) & (uint32_t(1) << ((type) & 31))) == 0);
521 }
522 
523 } /* namespace ns3 */
524 
void SetNode(Ptr< Node > node)
Set the node associated with this socket.
bool IsAny() const
If the IPv6 address is the "Any" address.
uint8_t GetTrafficClass(void) const
Get the "Traffic class" field.
Definition: ipv6-header.cc:50
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:268
void SetTclass(uint8_t tclass)
Set the tag's Tclass.
Definition: socket.cc:906
uint8_t GetNextHeader(void) const
Get the next header.
Definition: ipv6-header.cc:80
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:34
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
bool IsIpv6RecvHopLimit(void) const
Ask if the socket is currently passing information about IPv6 Hop Limit up the stack.
Definition: socket.cc:563
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
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:1160
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:44
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:462
void NotifyDataRecv(void)
Notify through the callback (if set) that some data have been received.
Definition: socket.cc:305
virtual uint32_t GetSerializedSize() const
Get the serialized size.
Ipv6Address fromIp
Source address.
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.
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:824
bool m_shutdownSend
Flag to shutdown send capability.
uint8_t GetType() const
Get the type field.
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.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:792
uint16_t fromProtocol
Protocol used.
Ptr< Packet > packet
Packet data.
virtual uint8_t GetIpv6HopLimit(void) const
Query the value of IP Hop Limit field of this socket.
Definition: socket.cc:551
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
SocketType
Enumeration of the possible socket types.
Definition: socket.h:104
virtual int GetPeerName(Address &address) const
Get the peer address of a connected socket.
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)
Ipv6Address m_ipv6MulticastGroupAddress
IPv6 multicast group address.
Definition: socket.h:1075
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:364
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's bound netdevice, if any.
Definition: socket.cc:351
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:228
A low-level Socket API based loosely on the BSD Socket API.
Definition: socket.h:66
ICMPv6 header.
Definition: icmpv6-header.h:38
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:340
Struct to hold the ICMPv6 filter.
Hold an unsigned integer type.
Definition: uinteger.h:44
virtual int GetSockName(Address &address) const
Get socket address.
uint8_t data[writeSize]
An Inet6 address class.
bool IsManualIpv6Tclass(void) const
Checks if the socket has a specific IPv6 Tclass set.
Definition: socket.cc:371
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.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:252
virtual Ptr< Node > GetNode() const
Return the node this socket is associated with.
void SetHopLimit(uint8_t hopLimit)
Set the tag's Hop Limit.
Definition: socket.cc:671
IPv6 raw data and additional information.
virtual int Listen()
Listen for incoming connections.
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:122
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:278
bool IsManualIpv6HopLimit(void) const
Checks if the socket has a specific IPv6 Hop Limit set.
Definition: socket.cc:383
uint8_t GetHopLimit(void) const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:90
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static uint16_t GetStaticProtocolNumber()
Get ICMPv6 protocol number.
bool Icmpv6FilterWillBlock(uint8_t type)
Ask the filter about the status of one ICMPv6 type.
indicates whether the socket has IPV6_TCLASS set.
Definition: socket.h:1351
uint8_t GetIpv6Tclass(void) const
Query the value of IPv6 Traffic Class field of this socket.
Definition: socket.cc:501
virtual void Ipv6LeaveGroup(void)
Leaves IPv6 multicast group this socket is joined to.
Definition: socket.cc:586
void Icmpv6FilterSetPass(uint8_t type)
Set the filter to pass one ICMPv6 type.
bool IsIpv6RecvTclass(void) const
Ask if the socket is currently passing information about IPv6 Traffic Class up the stack...
Definition: socket.cc:513
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.
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:90
virtual uint32_t GetRxAvailable() const
Return number of bytes which can be returned from one or multiple calls to Recv.
Describes an IPv6 address.
Definition: ipv6-address.h:48
virtual uint32_t GetTxAvailable() const
Returns the number of bytes which can be sent in a single call to Send.
enum Socket::SocketErrno m_err
Last error number.
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:1073
virtual int Close()
Close a socket.
Ipv6Address m_dst
Destination address.
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:831
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:100
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:236
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
Copy the packet contents to a byte buffer.
Definition: packet.cc:356
Ipv6MulticastFilterMode
Enumeration of the possible filter of a socket.
Definition: socket.h:138
This class implements a tag that carries socket ancillary data to the socket interface.
tuple address
Definition: first.py:37
Definition: first.py:1
virtual bool GetAllowBroadcast() const
Query whether broadcast datagram transmissions are allowed.
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
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:904
void SetRecvIf(uint32_t ifindex)
Set the tag's receiving interface.
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:257
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:110
uint16_t m_protocol
Protocol.
void Icmpv6FilterSetBlockAll()
Set the filter to block all the ICMPv6 types.