A Discrete-Event Network Simulator
API
ipv6-raw-socket-impl.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007-2009 Strasbourg University
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
18  */
19 
20 #include "ipv6-raw-socket-impl.h"
21 
22 #include "icmpv6-header.h"
23 #include "icmpv6-l4-protocol.h"
24 #include "ipv6-l3-protocol.h"
25 #include "ipv6-packet-info-tag.h"
26 #include "ipv6-route.h"
27 #include "ipv6-routing-protocol.h"
28 
29 #include "ns3/inet6-socket-address.h"
30 #include "ns3/log.h"
31 #include "ns3/node.h"
32 #include "ns3/packet.h"
33 #include "ns3/uinteger.h"
34 
35 #ifdef __WIN32__
36 #include "win32-internet.h"
37 #else
38 #include <netinet/in.h>
39 #include <sys/socket.h>
40 #endif
41 
42 #include <sys/types.h>
43 
44 namespace ns3
45 {
46 
47 NS_LOG_COMPONENT_DEFINE("Ipv6RawSocketImpl");
48 
49 NS_OBJECT_ENSURE_REGISTERED(Ipv6RawSocketImpl);
50 
51 TypeId
53 {
54  static TypeId tid = TypeId("ns3::Ipv6RawSocketImpl")
55  .SetParent<Socket>()
56  .SetGroupName("Internet")
57  .AddAttribute("Protocol",
58  "Protocol number to match.",
59  UintegerValue(0),
61  MakeUintegerChecker<uint16_t>());
62  return tid;
63 }
64 
66 {
67  NS_LOG_FUNCTION(this);
69  m_node = nullptr;
72  m_protocol = 0;
73  m_shutdownSend = false;
74  m_shutdownRecv = false;
76 }
77 
79 {
80 }
81 
82 void
84 {
85  NS_LOG_FUNCTION(this);
86  m_node = nullptr;
88 }
89 
90 void
92 {
93  NS_LOG_FUNCTION(this << node);
94  m_node = node;
95 }
96 
99 {
100  return m_node;
101 }
102 
105 {
106  NS_LOG_FUNCTION(this);
107  return m_err;
108 }
109 
112 {
113  return NS3_SOCK_RAW;
114 }
115 
116 int
118 {
119  NS_LOG_FUNCTION(this << address);
120 
122  {
124  return -1;
125  }
127  m_src = ad.GetIpv6();
128  return 0;
129 }
130 
131 int
133 {
134  NS_LOG_FUNCTION(this);
136  return 0;
137 }
138 
139 int
141 {
142  return Bind();
143 }
144 
145 int
147 {
148  NS_LOG_FUNCTION(this);
150  return 0;
151 }
152 
153 int
155 {
156  NS_LOG_FUNCTION(this << address);
157 
158  if (m_dst.IsAny())
159  {
161  return -1;
162  }
163 
165 
166  return 0;
167 }
168 
169 int
171 {
172  NS_LOG_FUNCTION(this);
174 
175  Ipv6LeaveGroup();
176  if (ipv6)
177  {
178  ipv6->DeleteRawSocket(this);
179  }
180  return 0;
181 }
182 
183 int
185 {
186  NS_LOG_FUNCTION(this);
187  m_shutdownSend = true;
188  return 0;
189 }
190 
191 int
193 {
194  NS_LOG_FUNCTION(this);
195  m_shutdownRecv = true;
196  return 0;
197 }
198 
199 int
201 {
202  NS_LOG_FUNCTION(this << address);
203 
205  {
208  return -1;
209  }
211  m_dst = ad.GetIpv6();
213 
214  return 0;
215 }
216 
217 int
219 {
220  NS_LOG_FUNCTION(this);
222  return -1;
223 }
224 
225 int
227 {
228  NS_LOG_FUNCTION(this << p << flags);
230  return SendTo(p, flags, to);
231 }
232 
233 int
234 Ipv6RawSocketImpl::SendTo(Ptr<Packet> p, uint32_t flags, const Address& toAddress)
235 {
236  NS_LOG_FUNCTION(this << p << flags << toAddress);
237 
238  if (!Inet6SocketAddress::IsMatchingType(toAddress))
239  {
241  return -1;
242  }
243 
244  if (m_shutdownSend)
245  {
246  return 0;
247  }
248 
251  Ipv6Address dst = ad.GetIpv6();
252 
253  if (IsManualIpv6Tclass())
254  {
255  SocketIpv6TclassTag ipTclassTag;
256  ipTclassTag.SetTclass(GetIpv6Tclass());
257  p->AddPacketTag(ipTclassTag);
258  }
259 
260  if (IsManualIpv6HopLimit() && GetIpv6HopLimit() != 0 && !dst.IsMulticast())
261  {
264  p->AddPacketTag(tag);
265  }
266 
267  if (ipv6->GetRoutingProtocol())
268  {
269  Ipv6Header hdr;
270  hdr.SetDestination(dst);
272  Ptr<Ipv6Route> route = nullptr;
273  Ptr<NetDevice> oif = m_boundnetdevice; // specify non-zero if bound to a specific device
274 
275  if (!m_src.IsAny())
276  {
277  int32_t index = ipv6->GetInterfaceForAddress(m_src);
278  NS_ASSERT(index >= 0);
279  oif = ipv6->GetNetDevice(index);
280  }
281 
282  route = ipv6->GetRoutingProtocol()->RouteOutput(p, hdr, oif, err);
283 
284  if (route)
285  {
286  NS_LOG_LOGIC("Route exists");
288  {
289  /* calculate checksum here for ICMPv6 echo request (sent by ping6)
290  * as we cannot determine source IPv6 address at application level
291  */
292  uint8_t type;
293  p->CopyData(&type, sizeof(type));
295  {
296  Icmpv6Echo hdr(true);
297  p->RemoveHeader(hdr);
298  hdr.CalculatePseudoHeaderChecksum(route->GetSource(),
299  dst,
300  p->GetSize() + hdr.GetSerializedSize(),
302  p->AddHeader(hdr);
303  }
304  }
305 
306  uint32_t pktSize = p->GetSize();
307  if (m_src.IsAny())
308  {
309  ipv6->Send(p, route->GetSource(), dst, m_protocol, route);
310  }
311  else
312  {
313  ipv6->Send(p, m_src, dst, m_protocol, route);
314  }
315  // Return only payload size (as Linux does).
318  return pktSize;
319  }
320  else
321  {
322  NS_LOG_DEBUG("No route, dropped!");
323  }
324  }
325  return 0;
326 }
327 
329 Ipv6RawSocketImpl::Recv(uint32_t maxSize, uint32_t flags)
330 {
331  NS_LOG_FUNCTION(this << maxSize << flags);
332  Address tmp;
333  return RecvFrom(maxSize, flags, tmp);
334 }
335 
337 Ipv6RawSocketImpl::RecvFrom(uint32_t maxSize, uint32_t flags, Address& fromAddress)
338 {
339  NS_LOG_FUNCTION(this << maxSize << flags << fromAddress);
340 
341  if (m_data.empty())
342  {
343  return nullptr;
344  }
345 
346  /* get packet */
347  Data data = m_data.front();
348  m_data.pop_front();
349  fromAddress = Inet6SocketAddress(data.fromIp, data.fromProtocol);
350  if (data.packet->GetSize() > maxSize)
351  {
352  Ptr<Packet> first = data.packet->CreateFragment(0, maxSize);
353  if (!(flags & MSG_PEEK))
354  {
355  data.packet->RemoveAtStart(maxSize);
356  }
357  m_data.push_front(data);
358  return first;
359  }
360 
361  return data.packet;
362 }
363 
364 void
367  std::vector<Ipv6Address> sourceAddresses)
368 {
369  NS_LOG_FUNCTION(this << address << &filterMode << &sourceAddresses);
370 
371  // We can join only one multicast group (or change its params)
373  "Can join only one IPv6 multicast group.");
374 
376 
378  if (ipv6l3)
379  {
380  if (filterMode == INCLUDE && sourceAddresses.empty())
381  {
382  // it is a leave
383  if (m_boundnetdevice)
384  {
385  int32_t index = ipv6l3->GetInterfaceForDevice(m_boundnetdevice);
386  NS_ASSERT_MSG(index >= 0, "Interface without a valid index");
387  ipv6l3->RemoveMulticastAddress(address, index);
388  }
389  else
390  {
391  ipv6l3->RemoveMulticastAddress(address);
392  }
393  }
394  else
395  {
396  // it is a join or a modification
397  if (m_boundnetdevice)
398  {
399  int32_t index = ipv6l3->GetInterfaceForDevice(m_boundnetdevice);
400  NS_ASSERT_MSG(index >= 0, "Interface without a valid index");
401  ipv6l3->AddMulticastAddress(address, index);
402  }
403  else
404  {
405  ipv6l3->AddMulticastAddress(address);
406  }
407  }
408  }
409 }
410 
411 uint32_t
413 {
414  NS_LOG_FUNCTION(this);
415  return 0xffffffff;
416 }
417 
418 uint32_t
420 {
421  NS_LOG_FUNCTION(this);
422  uint32_t rx = 0;
423 
424  for (auto it = m_data.begin(); it != m_data.end(); ++it)
425  {
426  rx += (it->packet)->GetSize();
427  }
428 
429  return rx;
430 }
431 
432 bool
434 {
435  NS_LOG_FUNCTION(this << *p << hdr << device);
436 
437  if (m_shutdownRecv)
438  {
439  return false;
440  }
441 
442  Ptr<NetDevice> boundNetDevice = Socket::GetBoundNetDevice();
443  if (boundNetDevice)
444  {
445  if (boundNetDevice != device)
446  {
447  return false;
448  }
449  }
450 
451  if ((m_src == Ipv6Address::GetAny() || hdr.GetDestination() == m_src) &&
452  (m_dst == Ipv6Address::GetAny() || hdr.GetSource() == m_dst) &&
453  hdr.GetNextHeader() == m_protocol)
454  {
455  Ptr<Packet> copy = p->Copy();
456 
458  {
459  /* filter */
460  Icmpv6Header icmpHeader;
461  copy->PeekHeader(icmpHeader);
462  uint8_t type = icmpHeader.GetType();
463 
465  {
466  /* packet filtered */
467  return false;
468  }
469  }
470 
471  // Should check via getsockopt ().
472  if (IsRecvPktInfo())
473  {
474  Ipv6PacketInfoTag tag;
475  copy->RemovePacketTag(tag);
476  tag.SetAddress(hdr.GetDestination());
477  tag.SetHoplimit(hdr.GetHopLimit());
478  tag.SetTrafficClass(hdr.GetTrafficClass());
479  tag.SetRecvIf(device->GetIfIndex());
480  copy->AddPacketTag(tag);
481  }
482 
483  // Check only version 6 options
484  if (IsIpv6RecvTclass())
485  {
486  SocketIpv6TclassTag ipTclassTag;
487  ipTclassTag.SetTclass(hdr.GetTrafficClass());
488  copy->AddPacketTag(ipTclassTag);
489  }
490 
491  if (IsIpv6RecvHopLimit())
492  {
493  SocketIpv6HopLimitTag ipHopLimitTag;
494  ipHopLimitTag.SetHopLimit(hdr.GetHopLimit());
495  copy->AddPacketTag(ipHopLimitTag);
496  }
497 
498  copy->AddHeader(hdr);
499  Data data;
500  data.packet = copy;
501  data.fromIp = hdr.GetSource();
502  data.fromProtocol = hdr.GetNextHeader();
503  m_data.push_back(data);
504  NotifyDataRecv();
505  return true;
506  }
507  return false;
508 }
509 
510 bool
512 {
513  return allowBroadcast;
514 }
515 
516 bool
518 {
519  return true;
520 }
521 
522 void
524 {
525  memset(&m_icmpFilter, 0xff, sizeof(Icmpv6Filter));
526 }
527 
528 void
530 {
531  memset(&m_icmpFilter, 0x00, sizeof(Icmpv6Filter));
532 }
533 
534 void
536 {
537  m_icmpFilter.icmpv6Filt[type >> 5] |= (uint32_t(1) << (type & 31));
538 }
539 
540 void
542 {
543  m_icmpFilter.icmpv6Filt[(type) >> 5] &= ~(uint32_t(1) << (type & 31));
544 }
545 
546 bool
548 {
549  return ((m_icmpFilter.icmpv6Filt[type >> 5]) & (uint32_t(1) << (type & 31))) != 0;
550 }
551 
552 bool
554 {
555  return ((m_icmpFilter.icmpv6Filt[type >> 5]) & (uint32_t(1) << (type & 31))) == 0;
556 }
557 
558 } /* namespace ns3 */
a polymophic address class
Definition: address.h:101
ICMPv6 Echo message.
uint32_t GetSerializedSize() const override
Get the serialized size.
ICMPv6 header.
Definition: icmpv6-header.h:38
uint8_t GetType() const
Get the type field.
void CalculatePseudoHeaderChecksum(Ipv6Address src, Ipv6Address dst, uint16_t length, uint8_t protocol)
Calculate pseudo header checksum for IPv6.
static uint16_t GetStaticProtocolNumber()
Get ICMPv6 protocol number.
An Inet6 address class.
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
static bool IsMatchingType(const Address &addr)
If the address match.
Ipv6Address GetIpv6() const
Get the IPv6 address.
Describes an IPv6 address.
Definition: ipv6-address.h:49
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
bool IsAny() const
If the IPv6 address is the "Any" address.
Packet header for IPv6.
Definition: ipv6-header.h:35
void SetDestination(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:118
uint8_t GetHopLimit() const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:100
uint8_t GetNextHeader() const
Get the next header.
Definition: ipv6-header.cc:88
Ipv6Address GetDestination() const
Get the "Destination address" field.
Definition: ipv6-header.cc:124
uint8_t GetTrafficClass() const
Get the "Traffic class" field.
Definition: ipv6-header.cc:52
Ipv6Address GetSource() const
Get the "Source address" field.
Definition: ipv6-header.cc:112
IPv6 layer implementation.
This class implements a tag that carries socket ancillary data to the socket interface.
void SetTrafficClass(uint8_t tclass)
Set the tag's Traffic Class.
void SetRecvIf(uint32_t ifindex)
Set the tag's receiving interface.
void SetHoplimit(uint8_t ttl)
Set the tag's Hop Limit.
void SetAddress(Ipv6Address addr)
Set the tag's address.
bool Icmpv6FilterWillBlock(uint8_t type)
Ask the filter about the status of one ICMPv6 type.
Socket::SocketErrno m_err
Last error number.
void Icmpv6FilterSetBlockAll()
Set the filter to block all the ICMPv6 types.
int Listen() override
Listen for incoming connections.
bool SetAllowBroadcast(bool allowBroadcast) override
Configure whether broadcast datagram transmissions are allowed.
int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress) override
Send data to a specified peer.
void SetNode(Ptr< Node > node)
Set the node associated with this socket.
uint32_t GetRxAvailable() const override
Return number of bytes which can be returned from one or multiple calls to Recv.
void Icmpv6FilterSetBlock(uint8_t type)
Set the filter to block one ICMPv6 type.
Ipv6Address m_src
Source address.
Icmpv6Filter m_icmpFilter
ICMPv6 filter.
int Bind6() override
Allocate a local IPv6 endpoint for this socket.
int Close() override
Close a socket.
int Send(Ptr< Packet > p, uint32_t flags) override
Send data (or dummy data) to the remote host.
int GetPeerName(Address &address) const override
Get the peer address of a connected socket.
bool GetAllowBroadcast() const override
Query whether broadcast datagram transmissions are allowed.
Ptr< Node > GetNode() const override
Return the node this socket is associated with.
Socket::SocketType GetSocketType() const override
Get socket type (NS3_SOCK_RAW)
static TypeId GetTypeId()
Get the type ID of this class.
bool m_shutdownRecv
Flag to shutdown receive capability.
Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress) override
Read a single packet from the socket and retrieve the sender address.
int Bind() override
Allocate a local IPv4 endpoint for this socket.
int GetSockName(Address &address) const override
Get socket address.
bool m_shutdownSend
Flag to shutdown send capability.
bool ForwardUp(Ptr< const Packet > p, Ipv6Header hdr, Ptr< NetDevice > device)
Forward up to receive method.
int Connect(const Address &address) override
Initiate a connection to a remote host.
bool Icmpv6FilterWillPass(uint8_t type)
Ask the filter about the status of one ICMPv6 type.
uint32_t GetTxAvailable() const override
Returns the number of bytes which can be sent in a single call to Send.
Socket::SocketErrno GetErrno() const override
Get last error number.
Ipv6Address m_dst
Destination address.
uint16_t m_protocol
Protocol.
void DoDispose() override
Dispose object.
std::list< Data > m_data
Packet waiting to be processed.
void Icmpv6FilterSetPass(uint8_t type)
Set the filter to pass one ICMPv6 type.
void Ipv6JoinGroup(Ipv6Address address, Socket::Ipv6MulticastFilterMode filterMode, std::vector< Ipv6Address > sourceAddresses) override
Joins a IPv6 multicast group.
void Icmpv6FilterSetPassAll()
Clean the ICMPv6 filter structure.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:967
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:400
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:960
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:305
A low-level Socket API based loosely on the BSD Socket API.
Definition: socket.h:68
Ptr< NetDevice > GetBoundNetDevice()
Returns socket's bound NetDevice, if any.
Definition: socket.cc:347
Ptr< Packet > Recv()
Read a single packet from the socket.
Definition: socket.cc:174
virtual void Ipv6LeaveGroup()
Leaves IPv6 multicast group this socket is joined to.
Definition: socket.cc:580
void NotifySend(uint32_t spaceAvailable)
Notify through the callback (if set) that some data have been sent.
Definition: socket.cc:292
bool IsRecvPktInfo() const
Get status indicating whether enable/disable packet information to socket.
Definition: socket.cc:361
Ipv6Address m_ipv6MulticastGroupAddress
IPv6 multicast group address.
Definition: socket.h:1082
SocketType
Enumeration of the possible socket types.
Definition: socket.h:107
@ NS3_SOCK_RAW
Definition: socket.h:111
void NotifyDataRecv()
Notify through the callback (if set) that some data have been received.
Definition: socket.cc:302
Ipv6MulticastFilterMode
Enumeration of the possible filter of a socket.
Definition: socket.h:143
Ptr< NetDevice > m_boundnetdevice
the device this socket is bound to (might be null).
Definition: socket.h:1079
bool IsIpv6RecvTclass() const
Ask if the socket is currently passing information about IPv6 Traffic Class up the stack.
Definition: socket.cc:504
bool IsIpv6RecvHopLimit() const
Ask if the socket is currently passing information about IPv6 Hop Limit up the stack.
Definition: socket.cc:554
virtual uint8_t GetIpv6HopLimit() const
Query the value of IP Hop Limit field of this socket.
Definition: socket.cc:542
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:84
@ ERROR_INVAL
Definition: socket.h:93
@ ERROR_OPNOTSUPP
Definition: socket.h:91
@ ERROR_NOTERROR
Definition: socket.h:85
@ ERROR_NOTCONN
Definition: socket.h:87
void NotifyDataSent(uint32_t size)
Notify through the callback (if set) that some data have been sent.
Definition: socket.cc:282
void NotifyConnectionSucceeded()
Notify through the callback (if set) that the connection has been established.
Definition: socket.cc:214
void DoDispose() override
Destructor implementation.
Definition: socket.cc:312
uint8_t GetIpv6Tclass() const
Query the value of IPv6 Traffic Class field of this socket.
Definition: socket.cc:492
bool IsManualIpv6HopLimit() const
Checks if the socket has a specific IPv6 Hop Limit set.
Definition: socket.cc:380
bool IsManualIpv6Tclass() const
Checks if the socket has a specific IPv6 Tclass set.
Definition: socket.cc:368
void NotifyConnectionFailed()
Notify through the callback (if set) that the connection has not been established due to an error.
Definition: socket.cc:224
This class implements a tag that carries the socket-specific HOPLIMIT of a packet to the IPv6 layer.
Definition: socket.h:1170
void SetHopLimit(uint8_t hopLimit)
Set the tag's Hop Limit.
Definition: socket.cc:668
indicates whether the socket has IPV6_TCLASS set.
Definition: socket.h:1364
void SetTclass(uint8_t tclass)
Set the tag's Tclass.
Definition: socket.cc:910
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
Hold an unsigned integer type.
Definition: uinteger.h:45
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#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:86
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Definition: first.py:1
address
Definition: first.py:47
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
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:132
uint8_t data[writeSize]
IPv6 raw data and additional information.
Struct to hold the ICMPv6 filter.
uint32_t icmpv6Filt[8]
ICMPv6 filter specification.
uint32_t pktSize
packet size used for the simulation (in bytes)