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;
351  return (this->Receive (packet, src, dst, fakeInterface));
352  }
353 
354  NS_LOG_LOGIC ("RX_ENDPOINT_UNREACH");
356  }
357 
358  packet->RemoveHeader(udpHeader);
359  for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin ();
360  endPoint != endPoints.end (); endPoint++)
361  {
362  (*endPoint)->ForwardUp (packet->Copy (), header, udpHeader.GetSourcePort (),
363  interface);
364  }
365  return IpL4Protocol::RX_OK;
366 }
367 
370  Ipv6Address &src,
371  Ipv6Address &dst,
372  Ptr<Ipv6Interface> interface)
373 {
374  NS_LOG_FUNCTION (this << packet << src << dst);
375  UdpHeader udpHeader;
376  if(Node::ChecksumEnabled ())
377  {
378  udpHeader.EnableChecksums ();
379  }
380 
381  udpHeader.InitializeChecksum (src, dst, PROT_NUMBER);
382 
383  packet->RemoveHeader (udpHeader);
384 
385  if(!udpHeader.IsChecksumOk () && !src.IsIpv4MappedAddress ())
386  {
387  NS_LOG_INFO ("Bad checksum : dropping packet!");
389  }
390 
391  NS_LOG_DEBUG ("Looking up dst " << dst << " port " << udpHeader.GetDestinationPort ());
392  Ipv6EndPointDemux::EndPoints endPoints =
393  m_endPoints6->Lookup (dst, udpHeader.GetDestinationPort (),
394  src, udpHeader.GetSourcePort (), interface);
395  if (endPoints.empty ())
396  {
397  NS_LOG_LOGIC ("RX_ENDPOINT_UNREACH");
399  }
400  for (Ipv6EndPointDemux::EndPointsI endPoint = endPoints.begin ();
401  endPoint != endPoints.end (); endPoint++)
402  {
403  (*endPoint)->ForwardUp (packet->Copy (), src, dst, udpHeader.GetSourcePort ());
404  }
405  return IpL4Protocol::RX_OK;
406 }
407 
408 void
410  Ipv4Address saddr, Ipv4Address daddr,
411  uint16_t sport, uint16_t dport)
412 {
413  NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport);
414 
415  UdpHeader udpHeader;
416  if(Node::ChecksumEnabled ())
417  {
418  udpHeader.EnableChecksums ();
419  udpHeader.InitializeChecksum (saddr,
420  daddr,
421  PROT_NUMBER);
422  }
423  udpHeader.SetDestinationPort (dport);
424  udpHeader.SetSourcePort (sport);
425 
426  packet->AddHeader (udpHeader);
427 
428  m_downTarget (packet, saddr, daddr, PROT_NUMBER, 0);
429 }
430 
431 void
433  Ipv4Address saddr, Ipv4Address daddr,
434  uint16_t sport, uint16_t dport, Ptr<Ipv4Route> route)
435 {
436  NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport << route);
437 
438  UdpHeader udpHeader;
439  if(Node::ChecksumEnabled ())
440  {
441  udpHeader.EnableChecksums ();
442  udpHeader.InitializeChecksum (saddr,
443  daddr,
444  PROT_NUMBER);
445  }
446  udpHeader.SetDestinationPort (dport);
447  udpHeader.SetSourcePort (sport);
448 
449  packet->AddHeader (udpHeader);
450 
451  m_downTarget (packet, saddr, daddr, PROT_NUMBER, route);
452 }
453 
454 void
456  Ipv6Address saddr, Ipv6Address daddr,
457  uint16_t sport, uint16_t dport)
458 {
459  NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport);
460 
461  UdpHeader udpHeader;
462  if(Node::ChecksumEnabled ())
463  {
464  udpHeader.EnableChecksums ();
465  udpHeader.InitializeChecksum (saddr,
466  daddr,
467  PROT_NUMBER);
468  }
469  udpHeader.SetDestinationPort (dport);
470  udpHeader.SetSourcePort (sport);
471 
472  packet->AddHeader (udpHeader);
473 
474  m_downTarget6 (packet, saddr, daddr, PROT_NUMBER, 0);
475 }
476 
477 void
479  Ipv6Address saddr, Ipv6Address daddr,
480  uint16_t sport, uint16_t dport, Ptr<Ipv6Route> route)
481 {
482  NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport << route);
483 
484  UdpHeader udpHeader;
485  if(Node::ChecksumEnabled ())
486  {
487  udpHeader.EnableChecksums ();
488  udpHeader.InitializeChecksum (saddr,
489  daddr,
490  PROT_NUMBER);
491  }
492  udpHeader.SetDestinationPort (dport);
493  udpHeader.SetSourcePort (sport);
494 
495  packet->AddHeader (udpHeader);
496 
497  m_downTarget6 (packet, saddr, daddr, PROT_NUMBER, route);
498 }
499 
500 void
502 {
503  NS_LOG_FUNCTION (this);
504  m_downTarget = callback;
505 }
506 
509 {
510  return m_downTarget;
511 }
512 
513 void
515 {
516  NS_LOG_FUNCTION (this);
517  m_downTarget6 = callback;
518 }
519 
522 {
523  return m_downTarget6;
524 }
525 
526 } // namespace ns3
527