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 
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 {
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 {
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 
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 = 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).
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.
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.
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 "...
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:831
Ipv6Address GetIpv6(void) const
Get the IPv6 address.
NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible")
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:146
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:202
virtual enum Socket::SocketType GetSocketType() const
Get socket type (NS3_SOCK_RAW)
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
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]
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
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:459
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:37
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.
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
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.
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:852
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:859
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:270
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
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:915
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.