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