A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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
21
22#include "icmpv6-header.h"
23#include "icmpv6-l4-protocol.h"
24#include "ipv6-l3-protocol.h"
26#include "ipv6-route.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
44namespace ns3
45{
46
47NS_LOG_COMPONENT_DEFINE("Ipv6RawSocketImpl");
48
49NS_OBJECT_ENSURE_REGISTERED(Ipv6RawSocketImpl);
50
51TypeId
53{
54 static TypeId tid = TypeId("ns3::Ipv6RawSocketImpl")
56 .SetGroupName("Internet")
57 .AddAttribute("Protocol",
58 "Protocol number to match.",
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
82void
84{
85 NS_LOG_FUNCTION(this);
86 m_node = nullptr;
88}
89
90void
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
116int
118{
119 NS_LOG_FUNCTION(this << address);
120
122 {
124 return -1;
125 }
127 m_src = ad.GetIpv6();
128 return 0;
129}
130
131int
133{
134 NS_LOG_FUNCTION(this);
136 return 0;
137}
138
139int
141{
142 return Bind();
143}
144
145int
147{
148 NS_LOG_FUNCTION(this);
149 address = Inet6SocketAddress(m_src, 0);
150 return 0;
151}
152
153int
155{
156 NS_LOG_FUNCTION(this << address);
157
158 if (m_dst.IsAny())
159 {
161 return -1;
162 }
163
164 address = Inet6SocketAddress(m_dst, 0);
165
166 return 0;
167}
168
169int
171{
172 NS_LOG_FUNCTION(this);
174
176 if (ipv6)
177 {
178 ipv6->DeleteRawSocket(this);
179 }
180 return 0;
181}
182
183int
185{
186 NS_LOG_FUNCTION(this);
187 m_shutdownSend = true;
188 return 0;
189}
190
191int
193{
194 NS_LOG_FUNCTION(this);
195 m_shutdownRecv = true;
196 return 0;
197}
198
199int
201{
202 NS_LOG_FUNCTION(this << address);
203
205 {
208 return -1;
209 }
211 m_dst = ad.GetIpv6();
213
214 return 0;
215}
216
217int
219{
220 NS_LOG_FUNCTION(this);
222 return -1;
223}
224
225int
227{
228 NS_LOG_FUNCTION(this << p << flags);
230 return SendTo(p, flags, to);
231}
232
233int
235{
236 NS_LOG_FUNCTION(this << p << flags << toAddress);
237
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
330{
331 NS_LOG_FUNCTION(this << maxSize << flags);
332 Address tmp;
333 return RecvFrom(maxSize, flags, tmp);
334}
335
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
364void
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
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
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
413{
414 NS_LOG_FUNCTION(this);
415 return 0xffffffff;
416}
417
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
432bool
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
464 if (Icmpv6FilterWillBlock(type))
465 {
466 /* packet filtered */
467 return false;
468 }
469 }
470
471 // Should check via getsockopt ().
472 if (IsRecvPktInfo())
473 {
475 copy->RemovePacketTag(tag);
476 tag.SetAddress(hdr.GetDestination());
477 tag.SetHoplimit(hdr.GetHopLimit());
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);
505 return true;
506 }
507 return false;
508}
509
510bool
512{
513 return allowBroadcast;
514}
515
516bool
518{
519 return true;
520}
521
522void
524{
525 memset(&m_icmpFilter, 0xff, sizeof(Icmpv6Filter));
526}
527
528void
530{
531 memset(&m_icmpFilter, 0x00, sizeof(Icmpv6Filter));
532}
533
534void
536{
537 m_icmpFilter.icmpv6Filt[type >> 5] |= (uint32_t(1) << (type & 31));
538}
539
540void
542{
543 m_icmpFilter.icmpv6Filt[(type) >> 5] &= ~(uint32_t(1) << (type & 31));
544}
545
546bool
548{
549 return ((m_icmpFilter.icmpv6Filt[type >> 5]) & (uint32_t(1) << (type & 31))) != 0;
550}
551
552bool
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:522
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
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:1084
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:1081
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:1172
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:1366
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:932
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
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
#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
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: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)