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"
35#include "icmpv6-header.h"
36#include "icmpv6-l4-protocol.h"
37
38namespace ns3
39{
40
41NS_LOG_COMPONENT_DEFINE ("Ipv6RawSocketImpl");
42
43NS_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
137int
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
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
203{
204 NS_LOG_FUNCTION (this << p << flags);
206 return SendTo (p, flags, to);
207}
208
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 {
239 p->AddPacketTag (tag);
240 }
241
242 if (ipv6->GetRoutingProtocol ())
243 {
244 Ipv6Header hdr;
245 hdr.SetDestination (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
301{
302 NS_LOG_FUNCTION (this << maxSize << flags);
303 Address tmp;
304 return RecvFrom (maxSize, flags, tmp);
305}
306
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
334void
335Ipv6RawSocketImpl::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
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
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.GetDestination () == m_src) &&
416 (m_dst == Ipv6Address::GetAny () || hdr.GetSource () == 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 {
439 copy->RemovePacketTag (tag);
440 tag.SetAddress (hdr.GetDestination ());
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.GetSource ();
466 data.fromProtocol = hdr.GetNextHeader ();
467 m_data.push_back (data);
469 return true;
470 }
471 return false;
472}
473
474bool
476{
477 if (!allowBroadcast)
478 {
479 return false;
480 }
481 return true;
482}
483
484bool
486{
487 return true;
488}
489
490void
492{
493 memset(&m_icmpFilter, 0xff, sizeof(Icmpv6Filter));
494}
495
496void
498{
499 memset(&m_icmpFilter, 0x00, sizeof(Icmpv6Filter));
500}
501
502void
504{
505 (m_icmpFilter.icmpv6Filt[(type) >> 5]) |= (uint32_t(1) << ((type) & 31));
506}
507
508void
510{
511 (m_icmpFilter.icmpv6Filt[(type) >> 5]) &= ~(uint32_t(1) << ((type) & 31));
512}
513
514bool
516{
517 return (((m_icmpFilter.icmpv6Filt[(type) >> 5]) & (uint32_t(1) << ((type) & 31))) != 0);
518}
519
520bool
522{
523 return (((m_icmpFilter.icmpv6Filt[(type) >> 5]) & (uint32_t(1) << ((type) & 31))) == 0);
524}
525
526} /* namespace ns3 */
527
a polymophic address class
Definition: address.h:91
ICMPv6 Echo message.
virtual uint32_t GetSerializedSize() const
Get the serialized size.
ICMPv6 header.
Definition: icmpv6-header.h:39
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(void) const
Get the IPv6 address.
Describes an IPv6 address.
Definition: ipv6-address.h:50
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:36
void SetDestination(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:115
uint8_t GetHopLimit(void) const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:90
Ipv6Address GetSource(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:105
uint8_t GetNextHeader(void) const
Get the next header.
Definition: ipv6-header.cc:80
uint8_t GetTrafficClass(void) const
Get the "Traffic class" field.
Definition: ipv6-header.cc:50
Ipv6Address GetDestination(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:125
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.
void Icmpv6FilterSetBlockAll()
Set the filter to block all the ICMPv6 types.
virtual int Listen()
Listen for incoming connections.
void SetNode(Ptr< Node > node)
Set the node associated with this socket.
virtual int Close()
Close a socket.
void Icmpv6FilterSetBlock(uint8_t type)
Set the filter to block one ICMPv6 type.
virtual bool GetAllowBroadcast() const
Query whether broadcast datagram transmissions are allowed.
Ipv6Address m_src
Source address.
virtual void DoDispose()
Dispose object.
Icmpv6Filter m_icmpFilter
ICMPv6 filter.
virtual int Connect(const Address &address)
Initiate a connection to a remote host.
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)
Read a single packet from the socket and retrieve the sender address.
static TypeId GetTypeId()
Get the type ID of this class.
virtual int Bind()
Allocate a local IPv4 endpoint for this socket.
virtual bool SetAllowBroadcast(bool allowBroadcast)
Configure whether broadcast datagram transmissions are allowed.
bool m_shutdownRecv
Flag to shutdown receive capability.
virtual int Send(Ptr< Packet > p, uint32_t flags)
Send data (or dummy data) to the remote host.
virtual void Ipv6JoinGroup(Ipv6Address address, Socket::Ipv6MulticastFilterMode filterMode, std::vector< Ipv6Address > sourceAddresses)
Joins a IPv6 multicast group.
virtual enum Socket::SocketErrno GetErrno() const
Get last error number.
bool m_shutdownSend
Flag to shutdown send capability.
bool ForwardUp(Ptr< const Packet > p, Ipv6Header hdr, Ptr< NetDevice > device)
Forward up to receive method.
bool Icmpv6FilterWillPass(uint8_t type)
Ask the filter about the status of one ICMPv6 type.
virtual uint32_t GetRxAvailable() const
Return number of bytes which can be returned from one or multiple calls to Recv.
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)
Send data to a specified peer.
virtual int Bind6()
Allocate a local IPv6 endpoint for this socket.
virtual int GetPeerName(Address &address) const
Get the peer address of a connected socket.
Ipv6Address m_dst
Destination address.
uint16_t m_protocol
Protocol.
virtual Ptr< Node > GetNode() const
Return the node this socket is associated with.
std::list< Data > m_data
Packet waiting to be processed.
void Icmpv6FilterSetPass(uint8_t type)
Set the filter to pass one ICMPv6 type.
virtual int GetSockName(Address &address) const
Get socket address.
virtual enum Socket::SocketType GetSocketType() const
Get socket type (NS3_SOCK_RAW)
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.
void Icmpv6FilterSetPassAll()
Clean the ICMPv6 filter structure.
virtual uint32_t GetIfIndex(void) const =0
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:963
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
A low-level Socket API based loosely on the BSD Socket API.
Definition: socket.h:67
Ptr< NetDevice > GetBoundNetDevice()
Returns socket's bound NetDevice, if any.
Definition: socket.cc:351
bool IsManualIpv6HopLimit(void) const
Checks if the socket has a specific IPv6 Hop Limit set.
Definition: socket.cc:383
uint8_t GetIpv6Tclass(void) const
Query the value of IPv6 Traffic Class field of this socket.
Definition: socket.cc:495
void NotifySend(uint32_t spaceAvailable)
Notify through the callback (if set) that some data have been sent.
Definition: socket.cc:295
bool IsRecvPktInfo() const
Get status indicating whether enable/disable packet information to socket.
Definition: socket.cc:364
virtual void DoDispose(void)
Destructor implementation.
Definition: socket.cc:315
bool IsIpv6RecvHopLimit(void) const
Ask if the socket is currently passing information about IPv6 Hop Limit up the stack.
Definition: socket.cc:557
Ipv6Address m_ipv6MulticastGroupAddress
IPv6 multicast group address.
Definition: socket.h:1079
bool IsIpv6RecvTclass(void) const
Ask if the socket is currently passing information about IPv6 Traffic Class up the stack.
Definition: socket.cc:507
SocketType
Enumeration of the possible socket types.
Definition: socket.h:104
@ NS3_SOCK_RAW
Definition: socket.h:108
void NotifyDataRecv(void)
Notify through the callback (if set) that some data have been received.
Definition: socket.cc:305
Ipv6MulticastFilterMode
Enumeration of the possible filter of a socket.
Definition: socket.h:139
Ptr< NetDevice > m_boundnetdevice
the device this socket is bound to (might be null).
Definition: socket.h:1077
virtual uint8_t GetIpv6HopLimit(void) const
Query the value of IP Hop Limit field of this socket.
Definition: socket.cc:545
bool IsManualIpv6Tclass(void) const
Checks if the socket has a specific IPv6 Tclass set.
Definition: socket.cc:371
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
@ ERROR_INVAL
Definition: socket.h:91
@ ERROR_OPNOTSUPP
Definition: socket.h:89
@ ERROR_NOTERROR
Definition: socket.h:83
@ ERROR_NOTCONN
Definition: socket.h:85
void NotifyDataSent(uint32_t size)
Notify through the callback (if set) that some data have been sent.
Definition: socket.cc:285
virtual void Ipv6LeaveGroup(void)
Leaves IPv6 multicast group this socket is joined to.
Definition: socket.cc:580
Ptr< Packet > Recv(void)
Read a single packet from the socket.
Definition: socket.cc:175
This class implements a tag that carries the socket-specific HOPLIMIT of a packet to the IPv6 layer.
Definition: socket.h:1165
void SetHopLimit(uint8_t hopLimit)
Set the tag's Hop Limit.
Definition: socket.cc:665
indicates whether the socket has IPV6_TCLASS set.
Definition: socket.h:1356
void SetTclass(uint8_t tclass)
Set the tag's Tclass.
Definition: socket.cc:900
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Hold an unsigned integer type.
Definition: uinteger.h:44
#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
#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
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:45
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#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:45
Definition: first.py:1
address
Definition: first.py:44
Every class exported by the ns3 library is enclosed in the ns3 namespace.
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:129
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)
Definition: wifi-bianchi.cc:89