A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
udp-l4-protocol.cc
Go to the documentation of this file.
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"
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
54 {
55  static TypeId tid = TypeId ("ns3::UdpL4Protocol")
57  .AddConstructor<UdpL4Protocol> ()
58  .AddAttribute ("SocketList", "The list of sockets associated to this protocol.",
61  MakeObjectVectorChecker<UdpSocketImpl> ())
62  ;
63  return tid;
64 }
65 
67  : m_endPoints (new Ipv4EndPointDemux ()), m_endPoints6 (new Ipv6EndPointDemux ())
68 {
70 }
71 
73 {
75 }
76 
77 void
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);
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;
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 *
174 {
176  return m_endPoints->Allocate ();
177 }
178 
179 Ipv4EndPoint *
181 {
182  NS_LOG_FUNCTION (this << address);
183  return m_endPoints->Allocate (address);
184 }
185 
186 Ipv4EndPoint *
188 {
189  NS_LOG_FUNCTION (this << port);
190  return m_endPoints->Allocate (port);
191 }
192 
193 Ipv4EndPoint *
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
210 {
211  NS_LOG_FUNCTION (this << endPoint);
212  m_endPoints->DeAllocate (endPoint);
213 }
214 
215 Ipv6EndPoint *
217 {
219  return m_endPoints6->Allocate ();
220 }
221 
222 Ipv6EndPoint *
224 {
225  NS_LOG_FUNCTION (this << address);
226  return m_endPoints6->Allocate (address);
227 }
228 
229 Ipv6EndPoint *
231 {
232  NS_LOG_FUNCTION (this << port);
233  return m_endPoints6->Allocate (port);
234 }
235 
236 Ipv6EndPoint *
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
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 
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!");
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");
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 
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!");
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");
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
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
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
517 {
518  NS_LOG_FUNCTION (this);
519  m_downTarget6 = callback;
520 }
521 
524 {
525  return m_downTarget6;
526 }
527 
528 } // namespace ns3
529