A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
udp-l4-protocol.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005 INRIA
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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 
21 #include "ns3/log.h"
22 #include "ns3/assert.h"
23 #include "ns3/packet.h"
24 #include "ns3/node.h"
25 #include "ns3/boolean.h"
26 #include "ns3/object-vector.h"
27 #include "ns3/ipv6.h"
28 #include "ns3/ipv4-route.h"
29 #include "ns3/ipv6-route.h"
30 #include "ns3/ipv6-header.h"
31 
32 #include "udp-l4-protocol.h"
33 #include "udp-header.h"
34 #include "udp-socket-factory-impl.h"
35 #include "ipv4-end-point-demux.h"
36 #include "ipv4-end-point.h"
37 #include "ipv6-end-point-demux.h"
38 #include "ipv6-end-point.h"
39 #include "ipv4-l3-protocol.h"
40 #include "ipv6-l3-protocol.h"
41 #include "udp-socket-impl.h"
42 
43 NS_LOG_COMPONENT_DEFINE ("UdpL4Protocol");
44 
45 namespace ns3 {
46 
47 NS_OBJECT_ENSURE_REGISTERED (UdpL4Protocol);
48 
49 /* see http://www.iana.org/assignments/protocol-numbers */
50 const uint8_t UdpL4Protocol::PROT_NUMBER = 17;
51 
52 TypeId
53 UdpL4Protocol::GetTypeId (void)
54 {
55  static TypeId tid = TypeId ("ns3::UdpL4Protocol")
56  .SetParent<IpL4Protocol> ()
57  .AddConstructor<UdpL4Protocol> ()
58  .AddAttribute ("SocketList", "The list of sockets associated to this protocol.",
59  ObjectVectorValue (),
60  MakeObjectVectorAccessor (&UdpL4Protocol::m_sockets),
61  MakeObjectVectorChecker<UdpSocketImpl> ())
62  ;
63  return tid;
64 }
65 
66 UdpL4Protocol::UdpL4Protocol ()
67  : m_endPoints (new Ipv4EndPointDemux ()), m_endPoints6 (new Ipv6EndPointDemux ())
68 {
70 }
71 
72 UdpL4Protocol::~UdpL4Protocol ()
73 {
75 }
76 
77 void
78 UdpL4Protocol::SetNode (Ptr<Node> node)
79 {
80  m_node = node;
81 }
82 
83 /*
84  * This method is called by AddAgregate and completes the aggregation
85  * by setting the node in the udp stack and link it to the ipv4 object
86  * present in the node along with the socket factory
87  */
88 void
90 {
91  NS_LOG_FUNCTION (this);
92  Ptr<Node> node = this->GetObject<Node> ();
93  Ptr<Ipv4> ipv4 = this->GetObject<Ipv4> ();
95 
96  if (m_node == 0)
97  {
98  if ((node != 0) && (ipv4 != 0 || ipv6 != 0))
99  {
100  this->SetNode (node);
101  Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> ();
102  udpFactory->SetUdp (this);
103  node->AggregateObject (udpFactory);
104  }
105  }
106 
107  // We set at least one of our 2 down targets to the IPv4/IPv6 send
108  // functions. Since these functions have different prototypes, we
109  // need to keep track of whether we are connected to an IPv4 or
110  // IPv6 lower layer and call the appropriate one.
111 
112  if (ipv4 != 0 && m_downTarget.IsNull())
113  {
114  ipv4->Insert (this);
115  this->SetDownTarget (MakeCallback (&Ipv4::Send, ipv4));
116  }
117  if (ipv6 != 0 && m_downTarget6.IsNull())
118  {
119  ipv6->Insert (this);
120  this->SetDownTarget6 (MakeCallback (&Ipv6L3Protocol::Send, ipv6));
121  }
123 }
124 
125 int
127 {
128  return PROT_NUMBER;
129 }
130 
131 
132 void
134 {
136  for (std::vector<Ptr<UdpSocketImpl> >::iterator i = m_sockets.begin (); i != m_sockets.end (); i++)
137  {
138  *i = 0;
139  }
140  m_sockets.clear ();
141 
142  if (m_endPoints != 0)
143  {
144  delete m_endPoints;
145  m_endPoints = 0;
146  }
147  if (m_endPoints6 != 0)
148  {
149  delete m_endPoints6;
150  m_endPoints6 = 0;
151  }
152  m_node = 0;
153  m_downTarget.Nullify ();
154  m_downTarget6.Nullify ();
155 /*
156  = MakeNullCallback<void,Ptr<Packet>, Ipv4Address, Ipv4Address, uint8_t, Ptr<Ipv4Route> > ();
157 */
159 }
160 
163 {
165  Ptr<UdpSocketImpl> socket = CreateObject<UdpSocketImpl> ();
166  socket->SetNode (m_node);
167  socket->SetUdp (this);
168  m_sockets.push_back (socket);
169  return socket;
170 }
171 
172 Ipv4EndPoint *
173 UdpL4Protocol::Allocate (void)
174 {
176  return m_endPoints->Allocate ();
177 }
178 
179 Ipv4EndPoint *
180 UdpL4Protocol::Allocate (Ipv4Address address)
181 {
182  NS_LOG_FUNCTION (this << address);
183  return m_endPoints->Allocate (address);
184 }
185 
186 Ipv4EndPoint *
187 UdpL4Protocol::Allocate (uint16_t port)
188 {
189  NS_LOG_FUNCTION (this << port);
190  return m_endPoints->Allocate (port);
191 }
192 
193 Ipv4EndPoint *
194 UdpL4Protocol::Allocate (Ipv4Address address, uint16_t port)
195 {
196  NS_LOG_FUNCTION (this << address << port);
197  return m_endPoints->Allocate (address, port);
198 }
199 Ipv4EndPoint *
200 UdpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort,
201  Ipv4Address peerAddress, uint16_t peerPort)
202 {
203  NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
204  return m_endPoints->Allocate (localAddress, localPort,
205  peerAddress, peerPort);
206 }
207 
208 void
209 UdpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint)
210 {
211  NS_LOG_FUNCTION (this << endPoint);
212  m_endPoints->DeAllocate (endPoint);
213 }
214 
215 Ipv6EndPoint *
216 UdpL4Protocol::Allocate6 (void)
217 {
219  return m_endPoints6->Allocate ();
220 }
221 
222 Ipv6EndPoint *
223 UdpL4Protocol::Allocate6 (Ipv6Address address)
224 {
225  NS_LOG_FUNCTION (this << address);
226  return m_endPoints6->Allocate (address);
227 }
228 
229 Ipv6EndPoint *
230 UdpL4Protocol::Allocate6 (uint16_t port)
231 {
232  NS_LOG_FUNCTION (this << port);
233  return m_endPoints6->Allocate (port);
234 }
235 
236 Ipv6EndPoint *
237 UdpL4Protocol::Allocate6 (Ipv6Address address, uint16_t port)
238 {
239  NS_LOG_FUNCTION (this << address << port);
240  return m_endPoints6->Allocate (address, port);
241 }
242 Ipv6EndPoint *
243 UdpL4Protocol::Allocate6 (Ipv6Address localAddress, uint16_t localPort,
244  Ipv6Address peerAddress, uint16_t peerPort)
245 {
246  NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
247  return m_endPoints6->Allocate (localAddress, localPort,
248  peerAddress, peerPort);
249 }
250 
251 void
252 UdpL4Protocol::DeAllocate (Ipv6EndPoint *endPoint)
253 {
254  NS_LOG_FUNCTION (this << endPoint);
255  m_endPoints6->DeAllocate (endPoint);
256 }
257 
258 void
259 UdpL4Protocol::ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
260  uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
261  Ipv4Address payloadSource,Ipv4Address payloadDestination,
262  const uint8_t payload[8])
263 {
264  NS_LOG_FUNCTION (this << icmpSource << icmpTtl << icmpType << icmpCode << icmpInfo
265  << payloadSource << payloadDestination);
266  uint16_t src, dst;
267  src = payload[0] << 8;
268  src |= payload[1];
269  dst = payload[2] << 8;
270  dst |= payload[3];
271 
272  Ipv4EndPoint *endPoint = m_endPoints->SimpleLookup (payloadSource, src, payloadDestination, dst);
273  if (endPoint != 0)
274  {
275  endPoint->ForwardIcmp (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
276  }
277  else
278  {
279  NS_LOG_DEBUG ("no endpoint found source=" << payloadSource <<
280  ", destination="<<payloadDestination<<
281  ", src=" << src << ", dst=" << dst);
282  }
283 }
284 
285 void
286 UdpL4Protocol::ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl,
287  uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
288  Ipv6Address payloadSource,Ipv6Address payloadDestination,
289  const uint8_t payload[8])
290 {
291  NS_LOG_FUNCTION (this << icmpSource << icmpTtl << icmpType << icmpCode << icmpInfo
292  << payloadSource << payloadDestination);
293  uint16_t src, dst;
294  src = payload[0] << 8;
295  src |= payload[1];
296  dst = payload[2] << 8;
297  dst |= payload[3];
298 
299  Ipv6EndPoint *endPoint = m_endPoints6->SimpleLookup (payloadSource, src, payloadDestination, dst);
300  if (endPoint != 0)
301  {
302  endPoint->ForwardIcmp (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
303  }
304  else
305  {
306  NS_LOG_DEBUG ("no endpoint found source=" << payloadSource <<
307  ", destination="<<payloadDestination<<
308  ", src=" << src << ", dst=" << dst);
309  }
310 }
311 
312 enum IpL4Protocol::RxStatus
314  Ipv4Header const &header,
315  Ptr<Ipv4Interface> interface)
316 {
317  NS_LOG_FUNCTION (this << packet << header);
318  UdpHeader udpHeader;
319  if(Node::ChecksumEnabled ())
320  {
321  udpHeader.EnableChecksums ();
322  }
323 
324  udpHeader.InitializeChecksum (header.GetSource (), header.GetDestination (), PROT_NUMBER);
325 
326  // We only peek at the header for now (instead of removing it) so that it will be intact
327  // if we have to pass it to a IPv6 endpoint via:
328  //
329  // UdpL4Protocol::Receive (Ptr<Packet> packet, Ipv6Address &src, Ipv6Address &dst, ...)
330 
331  packet->PeekHeader (udpHeader);
332 
333  if(!udpHeader.IsChecksumOk ())
334  {
335  NS_LOG_INFO ("Bad checksum : dropping packet!");
336  return IpL4Protocol::RX_CSUM_FAILED;
337  }
338 
339  NS_LOG_DEBUG ("Looking up dst " << header.GetDestination () << " port " << udpHeader.GetDestinationPort ());
340  Ipv4EndPointDemux::EndPoints endPoints =
341  m_endPoints->Lookup (header.GetDestination (), udpHeader.GetDestinationPort (),
342  header.GetSource (), udpHeader.GetSourcePort (), interface);
343  if (endPoints.empty ())
344  {
345  if (this->GetObject<Ipv6L3Protocol> () != 0)
346  {
347  NS_LOG_LOGIC (" No Ipv4 endpoints matched on UdpL4Protocol, trying Ipv6 "<<this);
348  Ptr<Ipv6Interface> fakeInterface;
349  Ipv6Header ipv6Header;
352  ipv6Header.SetSourceAddress (src);
353  ipv6Header.SetDestinationAddress (dst);
354  return (this->Receive (packet, ipv6Header, fakeInterface));
355  }
356 
357  NS_LOG_LOGIC ("RX_ENDPOINT_UNREACH");
358  return IpL4Protocol::RX_ENDPOINT_UNREACH;
359  }
360 
361  packet->RemoveHeader(udpHeader);
362  for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin ();
363  endPoint != endPoints.end (); endPoint++)
364  {
365  (*endPoint)->ForwardUp (packet->Copy (), header, udpHeader.GetSourcePort (),
366  interface);
367  }
368  return IpL4Protocol::RX_OK;
369 }
370 
371 enum IpL4Protocol::RxStatus
373  Ipv6Header const &header,
374  Ptr<Ipv6Interface> interface)
375 {
376  NS_LOG_FUNCTION (this << packet << header.GetSourceAddress () << header.GetDestinationAddress ());
377  UdpHeader udpHeader;
378  if(Node::ChecksumEnabled ())
379  {
380  udpHeader.EnableChecksums ();
381  }
382 
383  udpHeader.InitializeChecksum (header.GetSourceAddress (), header.GetDestinationAddress (), PROT_NUMBER);
384 
385  packet->RemoveHeader (udpHeader);
386 
387  if(!udpHeader.IsChecksumOk () && !header.GetSourceAddress ().IsIpv4MappedAddress ())
388  {
389  NS_LOG_INFO ("Bad checksum : dropping packet!");
390  return IpL4Protocol::RX_CSUM_FAILED;
391  }
392 
393  NS_LOG_DEBUG ("Looking up dst " << header.GetDestinationAddress () << " port " << udpHeader.GetDestinationPort ());
394  Ipv6EndPointDemux::EndPoints endPoints =
395  m_endPoints6->Lookup (header.GetDestinationAddress (), udpHeader.GetDestinationPort (),
396  header.GetSourceAddress (), udpHeader.GetSourcePort (), interface);
397  if (endPoints.empty ())
398  {
399  NS_LOG_LOGIC ("RX_ENDPOINT_UNREACH");
400  return IpL4Protocol::RX_ENDPOINT_UNREACH;
401  }
402  for (Ipv6EndPointDemux::EndPointsI endPoint = endPoints.begin ();
403  endPoint != endPoints.end (); endPoint++)
404  {
405  (*endPoint)->ForwardUp (packet->Copy (), header, udpHeader.GetSourcePort ());
406  }
407  return IpL4Protocol::RX_OK;
408 }
409 
410 void
412  Ipv4Address saddr, Ipv4Address daddr,
413  uint16_t sport, uint16_t dport)
414 {
415  NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport);
416 
417  UdpHeader udpHeader;
418  if(Node::ChecksumEnabled ())
419  {
420  udpHeader.EnableChecksums ();
421  udpHeader.InitializeChecksum (saddr,
422  daddr,
423  PROT_NUMBER);
424  }
425  udpHeader.SetDestinationPort (dport);
426  udpHeader.SetSourcePort (sport);
427 
428  packet->AddHeader (udpHeader);
429 
430  m_downTarget (packet, saddr, daddr, PROT_NUMBER, 0);
431 }
432 
433 void
435  Ipv4Address saddr, Ipv4Address daddr,
436  uint16_t sport, uint16_t dport, Ptr<Ipv4Route> route)
437 {
438  NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport << route);
439 
440  UdpHeader udpHeader;
441  if(Node::ChecksumEnabled ())
442  {
443  udpHeader.EnableChecksums ();
444  udpHeader.InitializeChecksum (saddr,
445  daddr,
446  PROT_NUMBER);
447  }
448  udpHeader.SetDestinationPort (dport);
449  udpHeader.SetSourcePort (sport);
450 
451  packet->AddHeader (udpHeader);
452 
453  m_downTarget (packet, saddr, daddr, PROT_NUMBER, route);
454 }
455 
456 void
457 UdpL4Protocol::Send (Ptr<Packet> packet,
458  Ipv6Address saddr, Ipv6Address daddr,
459  uint16_t sport, uint16_t dport)
460 {
461  NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport);
462 
463  UdpHeader udpHeader;
464  if(Node::ChecksumEnabled ())
465  {
466  udpHeader.EnableChecksums ();
467  udpHeader.InitializeChecksum (saddr,
468  daddr,
469  PROT_NUMBER);
470  }
471  udpHeader.SetDestinationPort (dport);
472  udpHeader.SetSourcePort (sport);
473 
474  packet->AddHeader (udpHeader);
475 
476  m_downTarget6 (packet, saddr, daddr, PROT_NUMBER, 0);
477 }
478 
479 void
480 UdpL4Protocol::Send (Ptr<Packet> packet,
481  Ipv6Address saddr, Ipv6Address daddr,
482  uint16_t sport, uint16_t dport, Ptr<Ipv6Route> route)
483 {
484  NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport << route);
485 
486  UdpHeader udpHeader;
487  if(Node::ChecksumEnabled ())
488  {
489  udpHeader.EnableChecksums ();
490  udpHeader.InitializeChecksum (saddr,
491  daddr,
492  PROT_NUMBER);
493  }
494  udpHeader.SetDestinationPort (dport);
495  udpHeader.SetSourcePort (sport);
496 
497  packet->AddHeader (udpHeader);
498 
499  m_downTarget6 (packet, saddr, daddr, PROT_NUMBER, route);
500 }
501 
502 void
504 {
505  NS_LOG_FUNCTION (this);
506  m_downTarget = callback;
507 }
508 
511 {
512  return m_downTarget;
513 }
514 
515 void
516 UdpL4Protocol::SetDownTarget6 (IpL4Protocol::DownTargetCallback6 callback)
517 {
518  NS_LOG_FUNCTION (this);
519  m_downTarget6 = callback;
520 }
521 
522 IpL4Protocol::DownTargetCallback6
523 UdpL4Protocol::GetDownTarget6 (void) const
524 {
525  return m_downTarget6;
526 }
527 
528 } // namespace ns3
529 
uint32_t RemoveHeader(Header &header)
Definition: packet.cc:285
Packet header for IPv6.
Definition: ipv6-header.h:33
Ptr< Socket > CreateSocket(void)
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
void InitializeChecksum(Address source, Address destination, uint8_t protocol)
Definition: udp-header.cc:74
virtual void DoDispose(void)
void Send(Ptr< Packet > packet, Ipv6Address source, Ipv6Address destination, uint8_t protocol, Ptr< Ipv6Route > route)
Higher-level layers call this method to send a packet down the stack to the MAC and PHY layers...
IPv6 layer implementation.
EndPoints Lookup(Ipv6Address dst, uint16_t dport, Ipv6Address src, uint16_t sport, Ptr< Ipv6Interface > incomingInterface)
lookup for a match with all the parameters.
virtual void SetDownTarget(IpL4Protocol::DownTargetCallback cb)
static bool ChecksumEnabled(void)
Definition: node.cc:267
void SetDestinationPort(uint16_t port)
Definition: udp-header.cc:54
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:303
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
void SetSourcePort(uint16_t port)
Definition: udp-header.cc:59
virtual void DoDispose(void)
Definition: object.cc:335
#define NS_LOG_INFO(msg)
Definition: log.h:264
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:290
#define NS_LOG_FUNCTION_NOARGS()
Definition: log.h:275
bool IsChecksumOk(void) const
Is the UDP checksum correct ?
Definition: udp-header.cc:135
virtual int GetProtocolNumber(void) const
Packet header for IPv4.
Definition: ipv4-header.h:31
virtual enum IpL4Protocol::RxStatus Receive(Ptr< Packet > p, Ipv4Header const &header, Ptr< Ipv4Interface > interface)
Receive a packet up the protocol stack.
void EnableChecksums(void)
Enable checksum calculation for UDP.
Definition: udp-header.cc:48
Ipv6EndPoint * Allocate(void)
Allocate a Ipv6EndPoint.
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:502
void AggregateObject(Ptr< Object > other)
Definition: object.cc:242
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
void DeAllocate(Ipv6EndPoint *endPoint)
Remove a end point.
virtual void NotifyNewAggregate(void)
Definition: object.cc:314
Ptr< Packet > Copy(void) const
Definition: packet.cc:131
uint32_t PeekHeader(Header &header) const
Definition: packet.cc:294
virtual void ReceiveIcmp(Ipv4Address icmpSource, uint8_t icmpTtl, uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo, Ipv4Address payloadSource, Ipv4Address payloadDestination, const uint8_t payload[8])
Receive an ICMP packet.
Ipv6EndPoint * SimpleLookup(Ipv6Address dst, uint16_t dport, Ipv6Address src, uint16_t sport)
Simple lookup for a four-tuple match.
uint16_t GetSourcePort(void) const
Definition: udp-header.cc:64
Packet header for UDP packets.
Definition: udp-header.h:39
virtual void Send(Ptr< Packet > packet, Ipv4Address source, Ipv4Address destination, uint8_t protocol, Ptr< Ipv4Route > route)=0
virtual IpL4Protocol::DownTargetCallback GetDownTarget(void) const
void SetSourceAddress(Ipv6Address src)
Set the "Source address" field.
Definition: ipv6-header.cc:96
Describes an IPv6 address.
Definition: ipv6-address.h:44
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:38
virtual void NotifyNewAggregate()
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:101
#define NS_LOG_DEBUG(msg)
Definition: log.h:255
An IPv6 end point, four tuples identification.
void Send(Ptr< Packet > packet, Ipv4Address saddr, Ipv4Address daddr, uint16_t sport, uint16_t dport)
Send a packet via UDP.
void ForwardIcmp(Ipv6Address src, uint8_t ttl, uint8_t type, uint8_t code, uint32_t info)
Function called from an L4Protocol implementation to notify an endpoint of an icmp message reception...
uint16_t GetDestinationPort(void) const
Definition: udp-header.cc:69
static Ipv6Address MakeIpv4MappedAddress(Ipv4Address addr)
Make the Ipv4-mapped IPv6 address.
Ptr< T > GetObject(void) const
Definition: object.h:332
void SetDestinationAddress(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:106
bool IsIpv4MappedAddress()
If the address is an IPv4-mapped address.
void AddHeader(const Header &header)
Definition: packet.cc:270
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:111
A representation of an internet endpoint/connection.