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 namespace ns3 {
44 
45 NS_LOG_COMPONENT_DEFINE ("UdpL4Protocol");
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
GetTypeId(void)53 UdpL4Protocol::GetTypeId (void)
54 {
55   static TypeId tid = TypeId ("ns3::UdpL4Protocol")
56     .SetParent<IpL4Protocol> ()
57     .SetGroupName ("Internet")
58     .AddConstructor<UdpL4Protocol> ()
59     .AddAttribute ("SocketList", "The list of sockets associated to this protocol.",
60                    ObjectVectorValue (),
61                    MakeObjectVectorAccessor (&UdpL4Protocol::m_sockets),
62                    MakeObjectVectorChecker<UdpSocketImpl> ())
63   ;
64   return tid;
65 }
66 
UdpL4Protocol()67 UdpL4Protocol::UdpL4Protocol ()
68   : m_endPoints (new Ipv4EndPointDemux ()), m_endPoints6 (new Ipv6EndPointDemux ())
69 {
70   NS_LOG_FUNCTION (this);
71 }
72 
~UdpL4Protocol()73 UdpL4Protocol::~UdpL4Protocol ()
74 {
75   NS_LOG_FUNCTION (this);
76 }
77 
78 void
SetNode(Ptr<Node> node)79 UdpL4Protocol::SetNode (Ptr<Node> node)
80 {
81   m_node = node;
82 }
83 
84 /*
85  * This method is called by AggregateObject and completes the aggregation
86  * by setting the node in the udp stack and link it to the ipv4 object
87  * present in the node along with the socket factory
88  */
89 void
NotifyNewAggregate()90 UdpL4Protocol::NotifyNewAggregate ()
91 {
92   NS_LOG_FUNCTION (this);
93   Ptr<Node> node = this->GetObject<Node> ();
94   Ptr<Ipv4> ipv4 = this->GetObject<Ipv4> ();
95   Ptr<Ipv6> ipv6 = node->GetObject<Ipv6> ();
96 
97   if (m_node == 0)
98     {
99       if ((node != 0) && (ipv4 != 0 || ipv6 != 0))
100         {
101           this->SetNode (node);
102           Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> ();
103           udpFactory->SetUdp (this);
104           node->AggregateObject (udpFactory);
105         }
106     }
107 
108   // We set at least one of our 2 down targets to the IPv4/IPv6 send
109   // functions.  Since these functions have different prototypes, we
110   // need to keep track of whether we are connected to an IPv4 or
111   // IPv6 lower layer and call the appropriate one.
112 
113   if (ipv4 != 0 && m_downTarget.IsNull())
114     {
115       ipv4->Insert (this);
116       this->SetDownTarget (MakeCallback (&Ipv4::Send, ipv4));
117     }
118   if (ipv6 != 0 && m_downTarget6.IsNull())
119     {
120       ipv6->Insert (this);
121       this->SetDownTarget6 (MakeCallback (&Ipv6::Send, ipv6));
122     }
123   IpL4Protocol::NotifyNewAggregate ();
124 }
125 
126 int
GetProtocolNumber(void) const127 UdpL4Protocol::GetProtocolNumber (void) const
128 {
129   return PROT_NUMBER;
130 }
131 
132 
133 void
DoDispose(void)134 UdpL4Protocol::DoDispose (void)
135 {
136   NS_LOG_FUNCTION (this);
137   for (std::vector<Ptr<UdpSocketImpl> >::iterator i = m_sockets.begin (); i != m_sockets.end (); i++)
138     {
139       *i = 0;
140     }
141   m_sockets.clear ();
142 
143   if (m_endPoints != 0)
144     {
145       delete m_endPoints;
146       m_endPoints = 0;
147     }
148   if (m_endPoints6 != 0)
149     {
150       delete m_endPoints6;
151       m_endPoints6 = 0;
152     }
153   m_node = 0;
154   m_downTarget.Nullify ();
155   m_downTarget6.Nullify ();
156 /*
157  = MakeNullCallback<void,Ptr<Packet>, Ipv4Address, Ipv4Address, uint8_t, Ptr<Ipv4Route> > ();
158 */
159   IpL4Protocol::DoDispose ();
160 }
161 
162 Ptr<Socket>
CreateSocket(void)163 UdpL4Protocol::CreateSocket (void)
164 {
165   NS_LOG_FUNCTION (this);
166   Ptr<UdpSocketImpl> socket = CreateObject<UdpSocketImpl> ();
167   socket->SetNode (m_node);
168   socket->SetUdp (this);
169   m_sockets.push_back (socket);
170   return socket;
171 }
172 
173 Ipv4EndPoint *
Allocate(void)174 UdpL4Protocol::Allocate (void)
175 {
176   NS_LOG_FUNCTION (this);
177   return m_endPoints->Allocate ();
178 }
179 
180 Ipv4EndPoint *
Allocate(Ipv4Address address)181 UdpL4Protocol::Allocate (Ipv4Address address)
182 {
183   NS_LOG_FUNCTION (this << address);
184   return m_endPoints->Allocate (address);
185 }
186 
187 Ipv4EndPoint *
Allocate(Ptr<NetDevice> boundNetDevice,uint16_t port)188 UdpL4Protocol::Allocate (Ptr<NetDevice> boundNetDevice, uint16_t port)
189 {
190   NS_LOG_FUNCTION (this << boundNetDevice << port);
191   return m_endPoints->Allocate (boundNetDevice, port);
192 }
193 
194 Ipv4EndPoint *
Allocate(Ptr<NetDevice> boundNetDevice,Ipv4Address address,uint16_t port)195 UdpL4Protocol::Allocate (Ptr<NetDevice> boundNetDevice, Ipv4Address address, uint16_t port)
196 {
197   NS_LOG_FUNCTION (this << boundNetDevice << address << port);
198   return m_endPoints->Allocate (boundNetDevice, address, port);
199 }
200 Ipv4EndPoint *
Allocate(Ptr<NetDevice> boundNetDevice,Ipv4Address localAddress,uint16_t localPort,Ipv4Address peerAddress,uint16_t peerPort)201 UdpL4Protocol::Allocate (Ptr<NetDevice> boundNetDevice,
202                          Ipv4Address localAddress, uint16_t localPort,
203                          Ipv4Address peerAddress, uint16_t peerPort)
204 {
205   NS_LOG_FUNCTION (this << boundNetDevice << localAddress << localPort << peerAddress << peerPort);
206   return m_endPoints->Allocate (boundNetDevice,
207                                 localAddress, localPort,
208                                 peerAddress, peerPort);
209 }
210 
211 void
DeAllocate(Ipv4EndPoint * endPoint)212 UdpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint)
213 {
214   NS_LOG_FUNCTION (this << endPoint);
215   m_endPoints->DeAllocate (endPoint);
216 }
217 
218 Ipv6EndPoint *
Allocate6(void)219 UdpL4Protocol::Allocate6 (void)
220 {
221   NS_LOG_FUNCTION (this);
222   return m_endPoints6->Allocate ();
223 }
224 
225 Ipv6EndPoint *
Allocate6(Ipv6Address address)226 UdpL4Protocol::Allocate6 (Ipv6Address address)
227 {
228   NS_LOG_FUNCTION (this << address);
229   return m_endPoints6->Allocate (address);
230 }
231 
232 Ipv6EndPoint *
Allocate6(Ptr<NetDevice> boundNetDevice,uint16_t port)233 UdpL4Protocol::Allocate6 (Ptr<NetDevice> boundNetDevice, uint16_t port)
234 {
235   NS_LOG_FUNCTION (this << boundNetDevice << port);
236   return m_endPoints6->Allocate (boundNetDevice, port);
237 }
238 
239 Ipv6EndPoint *
Allocate6(Ptr<NetDevice> boundNetDevice,Ipv6Address address,uint16_t port)240 UdpL4Protocol::Allocate6 (Ptr<NetDevice> boundNetDevice, Ipv6Address address, uint16_t port)
241 {
242   NS_LOG_FUNCTION (this << boundNetDevice << address << port);
243   return m_endPoints6->Allocate (boundNetDevice, address, port);
244 }
245 Ipv6EndPoint *
Allocate6(Ptr<NetDevice> boundNetDevice,Ipv6Address localAddress,uint16_t localPort,Ipv6Address peerAddress,uint16_t peerPort)246 UdpL4Protocol::Allocate6 (Ptr<NetDevice> boundNetDevice,
247                           Ipv6Address localAddress, uint16_t localPort,
248                           Ipv6Address peerAddress, uint16_t peerPort)
249 {
250   NS_LOG_FUNCTION (this << boundNetDevice << localAddress << localPort << peerAddress << peerPort);
251   return m_endPoints6->Allocate (boundNetDevice,
252                                  localAddress, localPort,
253                                  peerAddress, peerPort);
254 }
255 
256 void
DeAllocate(Ipv6EndPoint * endPoint)257 UdpL4Protocol::DeAllocate (Ipv6EndPoint *endPoint)
258 {
259   NS_LOG_FUNCTION (this << endPoint);
260   m_endPoints6->DeAllocate (endPoint);
261 }
262 
263 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])264 UdpL4Protocol::ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
265                             uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
266                             Ipv4Address payloadSource,Ipv4Address payloadDestination,
267                             const uint8_t payload[8])
268 {
269   NS_LOG_FUNCTION (this << icmpSource << icmpTtl << icmpType << icmpCode << icmpInfo
270                         << payloadSource << payloadDestination);
271   uint16_t src, dst;
272   src = payload[0] << 8;
273   src |= payload[1];
274   dst = payload[2] << 8;
275   dst |= payload[3];
276 
277   Ipv4EndPoint *endPoint = m_endPoints->SimpleLookup (payloadSource, src, payloadDestination, dst);
278   if (endPoint != 0)
279     {
280       endPoint->ForwardIcmp (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
281     }
282   else
283     {
284       NS_LOG_DEBUG ("no endpoint found source=" << payloadSource <<
285                     ", destination="<<payloadDestination<<
286                     ", src=" << src << ", dst=" << dst);
287     }
288 }
289 
290 void
ReceiveIcmp(Ipv6Address icmpSource,uint8_t icmpTtl,uint8_t icmpType,uint8_t icmpCode,uint32_t icmpInfo,Ipv6Address payloadSource,Ipv6Address payloadDestination,const uint8_t payload[8])291 UdpL4Protocol::ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl,
292                             uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
293                             Ipv6Address payloadSource,Ipv6Address payloadDestination,
294                             const uint8_t payload[8])
295 {
296   NS_LOG_FUNCTION (this << icmpSource << icmpTtl << icmpType << icmpCode << icmpInfo
297                         << payloadSource << payloadDestination);
298   uint16_t src, dst;
299   src = payload[0] << 8;
300   src |= payload[1];
301   dst = payload[2] << 8;
302   dst |= payload[3];
303 
304   Ipv6EndPoint *endPoint = m_endPoints6->SimpleLookup (payloadSource, src, payloadDestination, dst);
305   if (endPoint != 0)
306     {
307       endPoint->ForwardIcmp (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
308     }
309   else
310     {
311       NS_LOG_DEBUG ("no endpoint found source=" << payloadSource <<
312                     ", destination="<<payloadDestination<<
313                     ", src=" << src << ", dst=" << dst);
314     }
315 }
316 
317 enum IpL4Protocol::RxStatus
Receive(Ptr<Packet> packet,Ipv4Header const & header,Ptr<Ipv4Interface> interface)318 UdpL4Protocol::Receive (Ptr<Packet> packet,
319                         Ipv4Header const &header,
320                         Ptr<Ipv4Interface> interface)
321 {
322   NS_LOG_FUNCTION (this << packet << header);
323   UdpHeader udpHeader;
324   if(Node::ChecksumEnabled ())
325     {
326       udpHeader.EnableChecksums ();
327     }
328 
329   udpHeader.InitializeChecksum (header.GetSource (), header.GetDestination (), PROT_NUMBER);
330 
331   // We only peek at the header for now (instead of removing it) so that it will be intact
332   // if we have to pass it to a IPv6 endpoint via:
333   //
334   //   UdpL4Protocol::Receive (Ptr<Packet> packet, Ipv6Address &src, Ipv6Address &dst, ...)
335 
336   packet->PeekHeader (udpHeader);
337 
338   if(!udpHeader.IsChecksumOk ())
339     {
340       NS_LOG_INFO ("Bad checksum : dropping packet!");
341       return IpL4Protocol::RX_CSUM_FAILED;
342     }
343 
344   NS_LOG_DEBUG ("Looking up dst " << header.GetDestination () << " port " << udpHeader.GetDestinationPort ());
345   Ipv4EndPointDemux::EndPoints endPoints =
346     m_endPoints->Lookup (header.GetDestination (), udpHeader.GetDestinationPort (),
347                          header.GetSource (), udpHeader.GetSourcePort (), interface);
348   if (endPoints.empty ())
349     {
350       if (this->GetObject<Ipv6L3Protocol> () != 0)
351         {
352           NS_LOG_LOGIC ("  No Ipv4 endpoints matched on UdpL4Protocol, trying Ipv6 "<<this);
353           Ptr<Ipv6Interface> fakeInterface;
354           Ipv6Header ipv6Header;
355           Ipv6Address src = Ipv6Address::MakeIpv4MappedAddress (header.GetSource ());
356           Ipv6Address dst = Ipv6Address::MakeIpv4MappedAddress (header.GetDestination ());
357           ipv6Header.SetSource (src);
358           ipv6Header.SetDestination (dst);
359           return (this->Receive (packet, ipv6Header, fakeInterface));
360         }
361 
362       NS_LOG_LOGIC ("RX_ENDPOINT_UNREACH");
363       return IpL4Protocol::RX_ENDPOINT_UNREACH;
364     }
365 
366   packet->RemoveHeader(udpHeader);
367   for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin ();
368        endPoint != endPoints.end (); endPoint++)
369     {
370       (*endPoint)->ForwardUp (packet->Copy (), header, udpHeader.GetSourcePort (),
371                               interface);
372     }
373   return IpL4Protocol::RX_OK;
374 }
375 
376 enum IpL4Protocol::RxStatus
Receive(Ptr<Packet> packet,Ipv6Header const & header,Ptr<Ipv6Interface> interface)377 UdpL4Protocol::Receive (Ptr<Packet> packet,
378                         Ipv6Header const &header,
379                         Ptr<Ipv6Interface> interface)
380 {
381   NS_LOG_FUNCTION (this << packet << header.GetSource () << header.GetDestination ());
382   UdpHeader udpHeader;
383   if(Node::ChecksumEnabled ())
384     {
385       udpHeader.EnableChecksums ();
386     }
387 
388   udpHeader.InitializeChecksum (header.GetSource (), header.GetDestination (), PROT_NUMBER);
389 
390   packet->RemoveHeader (udpHeader);
391 
392   if(!udpHeader.IsChecksumOk () && !header.GetSource ().IsIpv4MappedAddress ())
393     {
394       NS_LOG_INFO ("Bad checksum : dropping packet!");
395       return IpL4Protocol::RX_CSUM_FAILED;
396     }
397 
398   NS_LOG_DEBUG ("Looking up dst " << header.GetDestination () << " port " << udpHeader.GetDestinationPort ());
399   Ipv6EndPointDemux::EndPoints endPoints =
400     m_endPoints6->Lookup (header.GetDestination (), udpHeader.GetDestinationPort (),
401                          header.GetSource (), udpHeader.GetSourcePort (), interface);
402   if (endPoints.empty ())
403     {
404       NS_LOG_LOGIC ("RX_ENDPOINT_UNREACH");
405       return IpL4Protocol::RX_ENDPOINT_UNREACH;
406     }
407   for (Ipv6EndPointDemux::EndPointsI endPoint = endPoints.begin ();
408        endPoint != endPoints.end (); endPoint++)
409     {
410       (*endPoint)->ForwardUp (packet->Copy (), header, udpHeader.GetSourcePort (), interface);
411     }
412   return IpL4Protocol::RX_OK;
413 }
414 
415 void
Send(Ptr<Packet> packet,Ipv4Address saddr,Ipv4Address daddr,uint16_t sport,uint16_t dport)416 UdpL4Protocol::Send (Ptr<Packet> packet,
417                      Ipv4Address saddr, Ipv4Address daddr,
418                      uint16_t sport, uint16_t dport)
419 {
420   NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport);
421 
422   UdpHeader udpHeader;
423   if(Node::ChecksumEnabled ())
424     {
425       udpHeader.EnableChecksums ();
426       udpHeader.InitializeChecksum (saddr,
427                                     daddr,
428                                     PROT_NUMBER);
429     }
430   udpHeader.SetDestinationPort (dport);
431   udpHeader.SetSourcePort (sport);
432 
433   packet->AddHeader (udpHeader);
434 
435   m_downTarget (packet, saddr, daddr, PROT_NUMBER, 0);
436 }
437 
438 void
Send(Ptr<Packet> packet,Ipv4Address saddr,Ipv4Address daddr,uint16_t sport,uint16_t dport,Ptr<Ipv4Route> route)439 UdpL4Protocol::Send (Ptr<Packet> packet,
440                      Ipv4Address saddr, Ipv4Address daddr,
441                      uint16_t sport, uint16_t dport, Ptr<Ipv4Route> route)
442 {
443   NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport << route);
444 
445   UdpHeader udpHeader;
446   if(Node::ChecksumEnabled ())
447     {
448       udpHeader.EnableChecksums ();
449       udpHeader.InitializeChecksum (saddr,
450                                     daddr,
451                                     PROT_NUMBER);
452     }
453   udpHeader.SetDestinationPort (dport);
454   udpHeader.SetSourcePort (sport);
455 
456   packet->AddHeader (udpHeader);
457 
458   m_downTarget (packet, saddr, daddr, PROT_NUMBER, route);
459 }
460 
461 void
Send(Ptr<Packet> packet,Ipv6Address saddr,Ipv6Address daddr,uint16_t sport,uint16_t dport)462 UdpL4Protocol::Send (Ptr<Packet> packet,
463                      Ipv6Address saddr, Ipv6Address daddr,
464                      uint16_t sport, uint16_t dport)
465 {
466   NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport);
467 
468   UdpHeader udpHeader;
469   if(Node::ChecksumEnabled ())
470     {
471       udpHeader.EnableChecksums ();
472       udpHeader.InitializeChecksum (saddr,
473                                     daddr,
474                                     PROT_NUMBER);
475     }
476   udpHeader.SetDestinationPort (dport);
477   udpHeader.SetSourcePort (sport);
478 
479   packet->AddHeader (udpHeader);
480 
481   m_downTarget6 (packet, saddr, daddr, PROT_NUMBER, 0);
482 }
483 
484 void
Send(Ptr<Packet> packet,Ipv6Address saddr,Ipv6Address daddr,uint16_t sport,uint16_t dport,Ptr<Ipv6Route> route)485 UdpL4Protocol::Send (Ptr<Packet> packet,
486                      Ipv6Address saddr, Ipv6Address daddr,
487                      uint16_t sport, uint16_t dport, Ptr<Ipv6Route> route)
488 {
489   NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport << route);
490 
491   UdpHeader udpHeader;
492   if(Node::ChecksumEnabled ())
493     {
494       udpHeader.EnableChecksums ();
495       udpHeader.InitializeChecksum (saddr,
496                                     daddr,
497                                     PROT_NUMBER);
498     }
499   udpHeader.SetDestinationPort (dport);
500   udpHeader.SetSourcePort (sport);
501 
502   packet->AddHeader (udpHeader);
503 
504   m_downTarget6 (packet, saddr, daddr, PROT_NUMBER, route);
505 }
506 
507 void
SetDownTarget(IpL4Protocol::DownTargetCallback callback)508 UdpL4Protocol::SetDownTarget (IpL4Protocol::DownTargetCallback callback)
509 {
510   NS_LOG_FUNCTION (this);
511   m_downTarget = callback;
512 }
513 
514 IpL4Protocol::DownTargetCallback
GetDownTarget(void) const515 UdpL4Protocol::GetDownTarget (void) const
516 {
517   return m_downTarget;
518 }
519 
520 void
SetDownTarget6(IpL4Protocol::DownTargetCallback6 callback)521 UdpL4Protocol::SetDownTarget6 (IpL4Protocol::DownTargetCallback6 callback)
522 {
523   NS_LOG_FUNCTION (this);
524   m_downTarget6 = callback;
525 }
526 
527 IpL4Protocol::DownTargetCallback6
GetDownTarget6(void) const528 UdpL4Protocol::GetDownTarget6 (void) const
529 {
530   return m_downTarget6;
531 }
532 
533 } // namespace ns3
534 
535