1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
3
* Copyright (c) 2007-2009 Strasbourg University
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;
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.
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
18
* Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
21
#include <netinet/in.h>
22
#include <sys/socket.h>
23
#include <sys/types.h>
24
#include "ns3/inet6-socket-address.h"
26
#include "ns3/packet.h"
27
#include "ns3/uinteger.h"
29
#include "ns3/ipv6-route.h"
30
#include "ns3/ipv6-routing-protocol.h"
31
#include "ns3/ipv6-packet-info-tag.h"
33
#include "ipv6-l3-protocol.h"
34
#include "ipv6-raw-socket-impl.h"
35
#include "icmpv6-header.h"
36
#include "icmpv6-l4-protocol.h"
41
NS_LOG_COMPONENT_DEFINE ("Ipv6RawSocketImpl");
44
NS_OBJECT_ENSURE_REGISTERED (Ipv6RawSocketImpl);
46
TypeId Ipv6RawSocketImpl::GetTypeId ()
48
static TypeId tid = TypeId ("ns3::Ipv6RawSocketImpl")
50
.AddAttribute ("Protocol", "Protocol number to match.",
52
MakeUintegerAccessor (&Ipv6RawSocketImpl::m_protocol),
53
MakeUintegerChecker<uint16_t> ())
54
.AddAttribute ("IcmpFilter", "Any ICMPv6 header whose type field matches a bit in this filter is dropped.",
56
MakeUintegerAccessor (&Ipv6RawSocketImpl::m_icmpFilter),
57
MakeUintegerChecker<uint32_t> ())
62
Ipv6RawSocketImpl::Ipv6RawSocketImpl ()
64
NS_LOG_FUNCTION_NOARGS ();
65
m_err = Socket::ERROR_NOTERROR;
67
m_src = Ipv6Address::GetAny ();
68
m_dst = Ipv6Address::GetAny ();
70
m_shutdownSend = false;
71
m_shutdownRecv = false;
74
Ipv6RawSocketImpl::~Ipv6RawSocketImpl ()
78
void Ipv6RawSocketImpl::DoDispose ()
80
NS_LOG_FUNCTION_NOARGS ();
85
void Ipv6RawSocketImpl::SetNode (Ptr<Node> node)
87
NS_LOG_FUNCTION (this << node);
91
Ptr<Node> Ipv6RawSocketImpl::GetNode () const
96
enum Socket::SocketErrno Ipv6RawSocketImpl::GetErrno () const
98
NS_LOG_FUNCTION_NOARGS ();
102
enum Socket::SocketType Ipv6RawSocketImpl::GetSocketType () const
107
int Ipv6RawSocketImpl::Bind (const Address& address)
109
NS_LOG_FUNCTION (this << address);
111
if (!Inet6SocketAddress::IsMatchingType (address))
113
m_err = Socket::ERROR_INVAL;
116
Inet6SocketAddress ad = Inet6SocketAddress::ConvertFrom (address);
117
m_src = ad.GetIpv6 ();
121
int Ipv6RawSocketImpl::Bind ()
123
NS_LOG_FUNCTION_NOARGS ();
124
m_src = Ipv6Address::GetAny ();
128
int Ipv6RawSocketImpl::GetSockName (Address& address) const
130
NS_LOG_FUNCTION_NOARGS ();
131
address = Inet6SocketAddress (m_src, 0);
135
int Ipv6RawSocketImpl::Close ()
137
NS_LOG_FUNCTION_NOARGS ();
138
Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
142
ipv6->DeleteRawSocket (this);
147
int Ipv6RawSocketImpl::ShutdownSend ()
149
NS_LOG_FUNCTION_NOARGS ();
150
m_shutdownSend = true;
154
int Ipv6RawSocketImpl::ShutdownRecv ()
156
NS_LOG_FUNCTION_NOARGS ();
157
m_shutdownRecv = true;
161
int Ipv6RawSocketImpl::Connect (const Address& address)
163
NS_LOG_FUNCTION (this << address);
165
if (!Inet6SocketAddress::IsMatchingType (address))
167
m_err = Socket::ERROR_INVAL;
171
Inet6SocketAddress ad = Inet6SocketAddress::ConvertFrom (address);
172
m_dst = ad.GetIpv6 ();
176
int Ipv6RawSocketImpl::Listen ()
178
NS_LOG_FUNCTION_NOARGS ();
179
m_err = Socket::ERROR_OPNOTSUPP;
183
int Ipv6RawSocketImpl::Send (Ptr<Packet> p, uint32_t flags)
185
NS_LOG_FUNCTION (this << p << flags);
186
Inet6SocketAddress to = Inet6SocketAddress (m_dst, m_protocol);
187
return SendTo (p, flags, to);
190
int Ipv6RawSocketImpl::SendTo (Ptr<Packet> p, uint32_t flags, const Address& toAddress)
192
NS_LOG_FUNCTION (this << p << flags << toAddress);
194
if (!Inet6SocketAddress::IsMatchingType (toAddress))
196
m_err = Socket::ERROR_INVAL;
205
Inet6SocketAddress ad = Inet6SocketAddress::ConvertFrom (toAddress);
206
Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
207
Ipv6Address dst = ad.GetIpv6 ();
209
if (ipv6->GetRoutingProtocol ())
212
hdr.SetDestinationAddress (dst);
213
SocketErrno err = ERROR_NOTERROR;
214
Ptr<Ipv6Route> route = 0;
215
Ptr<NetDevice> oif (0); /*specify non-zero if bound to a source address */
219
int32_t index = ipv6->GetInterfaceForAddress (m_src);
220
NS_ASSERT (index >= 0);
221
oif = ipv6->GetNetDevice (index);
224
route = ipv6->GetRoutingProtocol ()->RouteOutput (p, hdr, oif, err);
228
NS_LOG_LOGIC ("Route exists");
229
if (m_protocol == Icmpv6L4Protocol::GetStaticProtocolNumber ())
231
/* calculate checksum here for ICMPv6 echo request (sent by ping6)
232
* as we cannot determine source IPv6 address at application level
235
p->CopyData (&type, sizeof(type));
236
if (type == Icmpv6Header::ICMPV6_ECHO_REQUEST)
239
p->RemoveHeader (hdr);
240
hdr.CalculatePseudoHeaderChecksum (route->GetSource (), dst, p->GetSize () + hdr.GetSerializedSize (), Icmpv6L4Protocol::GetStaticProtocolNumber ());
245
ipv6->Send (p, route->GetSource (), dst, m_protocol, route);
249
NS_LOG_DEBUG ("No route, dropped!");
255
Ptr<Packet> Ipv6RawSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
257
NS_LOG_FUNCTION (this << maxSize << flags);
259
return RecvFrom (maxSize, flags, tmp);
262
Ptr<Packet> Ipv6RawSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags, Address& fromAddress)
264
NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
272
struct Data data = m_data.front ();
275
if (data.packet->GetSize () > maxSize)
277
Ptr<Packet> first = data.packet->CreateFragment (0, maxSize);
278
if (!(flags & MSG_PEEK))
280
data.packet->RemoveAtStart (maxSize);
282
m_data.push_front (data);
286
fromAddress = Inet6SocketAddress (data.fromIp, data.fromProtocol);
290
uint32_t Ipv6RawSocketImpl::GetTxAvailable () const
292
NS_LOG_FUNCTION_NOARGS ();
296
uint32_t Ipv6RawSocketImpl::GetRxAvailable () const
298
NS_LOG_FUNCTION_NOARGS ();
301
for (std::list<Data>::const_iterator it = m_data.begin (); it != m_data.end (); ++it)
303
rx+= (it->packet)->GetSize ();
309
bool Ipv6RawSocketImpl::ForwardUp (Ptr<const Packet> p, Ipv6Header hdr, Ptr<NetDevice> device)
311
NS_LOG_FUNCTION (this << *p << hdr << device);
318
if ((m_src == Ipv6Address::GetAny () || hdr.GetDestinationAddress () == m_src) &&
319
(m_dst == Ipv6Address::GetAny () || hdr.GetSourceAddress () == m_dst) &&
320
hdr.GetNextHeader () == m_protocol)
322
Ptr<Packet> copy = p->Copy ();
324
if (m_protocol == Icmpv6L4Protocol::GetStaticProtocolNumber ())
327
Icmpv6Header icmpHeader;
328
copy->PeekHeader (icmpHeader);
329
uint8_t type = icmpHeader.GetType ();
331
if ((1 << type) & m_icmpFilter)
333
/* packet filtered */
338
// Should check via getsockopt ()..
339
if (this->m_recvpktinfo)
341
Ipv6PacketInfoTag tag;
342
copy->RemovePacketTag (tag);
343
tag.SetRecvIf (device->GetIfIndex ());
344
copy->AddPacketTag (tag);
347
copy->AddHeader (hdr);
350
data.fromIp = hdr.GetSourceAddress ();
351
data.fromProtocol = hdr.GetNextHeader ();
352
m_data.push_back (data);
360
Ipv6RawSocketImpl::SetAllowBroadcast (bool allowBroadcast)
370
Ipv6RawSocketImpl::GetAllowBroadcast () const
375
} /* namespace ns3 */