A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
udp-socket-impl.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007 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/node.h"
23 #include "ns3/inet-socket-address.h"
24 #include "ns3/inet6-socket-address.h"
25 #include "ns3/ipv4-route.h"
26 #include "ns3/ipv6-route.h"
27 #include "ns3/ipv4.h"
28 #include "ns3/ipv6.h"
29 #include "ns3/ipv4-header.h"
30 #include "ns3/ipv4-routing-protocol.h"
31 #include "ns3/ipv6-routing-protocol.h"
32 #include "ns3/udp-socket-factory.h"
33 #include "ns3/trace-source-accessor.h"
34 #include "ns3/ipv4-packet-info-tag.h"
35 #include "udp-socket-impl.h"
36 #include "udp-l4-protocol.h"
37 #include "ipv4-end-point.h"
38 #include "ipv6-end-point.h"
39 #include <limits>
40 
41 NS_LOG_COMPONENT_DEFINE ("UdpSocketImpl");
42 
43 namespace ns3 {
44 
45 NS_OBJECT_ENSURE_REGISTERED (UdpSocketImpl);
46 
47 static const uint32_t MAX_IPV4_UDP_DATAGRAM_SIZE = 65507;
48 
49 // Add attributes generic to all UdpSockets to base class UdpSocket
50 TypeId
52 {
53  static TypeId tid = TypeId ("ns3::UdpSocketImpl")
54  .SetParent<UdpSocket> ()
55  .AddConstructor<UdpSocketImpl> ()
56  .AddTraceSource ("Drop", "Drop UDP packet due to receive buffer overflow",
58  .AddAttribute ("IcmpCallback", "Callback invoked whenever an icmp error is received on this socket.",
59  CallbackValue (),
60  MakeCallbackAccessor (&UdpSocketImpl::m_icmpCallback),
61  MakeCallbackChecker ())
62  .AddAttribute ("IcmpCallback6", "Callback invoked whenever an icmpv6 error is received on this socket.",
63  CallbackValue (),
64  MakeCallbackAccessor (&UdpSocketImpl::m_icmpCallback6),
65  MakeCallbackChecker ())
66  ;
67  return tid;
68 }
69 
71  : m_endPoint (0),
72  m_endPoint6 (0),
73  m_node (0),
74  m_udp (0),
75  m_errno (ERROR_NOTERROR),
76  m_shutdownSend (false),
77  m_shutdownRecv (false),
78  m_connected (false),
79  m_rxAvailable (0)
80 {
82  m_allowBroadcast = false;
83 }
84 
86 {
88 
89  // XXX todo: leave any multicast groups that have been joined
90  m_node = 0;
96  if (m_endPoint != 0)
97  {
98  NS_ASSERT (m_udp != 0);
107  NS_ASSERT (m_endPoint != 0);
109  NS_ASSERT (m_endPoint == 0);
110  }
111  if (m_endPoint6 != 0)
112  {
113  NS_ASSERT (m_udp != 0);
122  NS_ASSERT (m_endPoint6 != 0);
124  NS_ASSERT (m_endPoint6 == 0);
125  }
126  m_udp = 0;
127 }
128 
129 void
131 {
133  m_node = node;
134 
135 }
136 void
138 {
140  m_udp = udp;
141 }
142 
143 
146 {
148  return m_errno;
149 }
150 
153 {
154  return NS3_SOCK_DGRAM;
155 }
156 
157 Ptr<Node>
159 {
161  return m_node;
162 }
163 
164 void
166 {
168  m_endPoint = 0;
169 }
170 
171 void
173 {
175  m_endPoint6 = 0;
176 }
177 
178 int
180 {
182  bool done = false;
183  if (m_endPoint != 0)
184  {
188  done = true;
189  }
190  if (m_endPoint6 != 0)
191  {
195  done = true;
196  }
197  if (done)
198  {
199  return 0;
200  }
201  return -1;
202 }
203 
204 int
206 {
208  m_endPoint = m_udp->Allocate ();
209  return FinishBind ();
210 }
211 
212 int
214 {
217  return FinishBind ();
218 }
219 
220 int
221 UdpSocketImpl::Bind (const Address &address)
222 {
223  NS_LOG_FUNCTION (this << address);
224 
225  if (InetSocketAddress::IsMatchingType (address))
226  {
228  Ipv4Address ipv4 = transport.GetIpv4 ();
229  uint16_t port = transport.GetPort ();
230  if (ipv4 == Ipv4Address::GetAny () && port == 0)
231  {
232  m_endPoint = m_udp->Allocate ();
233  }
234  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
235  {
236  m_endPoint = m_udp->Allocate (port);
237  }
238  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
239  {
240  m_endPoint = m_udp->Allocate (ipv4);
241  }
242  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
243  {
244  m_endPoint = m_udp->Allocate (ipv4, port);
245  }
246  }
247  else if (Inet6SocketAddress::IsMatchingType (address))
248  {
250  Ipv6Address ipv6 = transport.GetIpv6 ();
251  uint16_t port = transport.GetPort ();
252  if (ipv6 == Ipv6Address::GetAny () && port == 0)
253  {
255  }
256  else if (ipv6 == Ipv6Address::GetAny () && port != 0)
257  {
258  m_endPoint6 = m_udp->Allocate6 (port);
259  }
260  else if (ipv6 != Ipv6Address::GetAny () && port == 0)
261  {
262  m_endPoint6 = m_udp->Allocate6 (ipv6);
263  }
264  else if (ipv6 != Ipv6Address::GetAny () && port != 0)
265  {
266  m_endPoint6 = m_udp->Allocate6 (ipv6, port);
267  }
268  }
269  else
270  {
271  NS_LOG_ERROR ("Not IsMatchingType");
273  return -1;
274  }
275 
276  return FinishBind ();
277 }
278 
279 int
281 {
283  m_shutdownSend = true;
284  return 0;
285 }
286 
287 int
289 {
291  m_shutdownRecv = true;
292  return 0;
293 }
294 
295 int
297 {
299  if (m_shutdownRecv == true && m_shutdownSend == true)
300  {
302  return -1;
303  }
304  m_shutdownRecv = true;
305  m_shutdownSend = true;
306  return 0;
307 }
308 
309 int
311 {
312  NS_LOG_FUNCTION (this << address);
313  if (InetSocketAddress::IsMatchingType(address) == true)
314  {
316  m_defaultAddress = Address(transport.GetIpv4 ());
317  m_defaultPort = transport.GetPort ();
318  m_connected = true;
320  }
321  else if (Inet6SocketAddress::IsMatchingType(address) == true)
322  {
324  m_defaultAddress = Address(transport.GetIpv6 ());
325  m_defaultPort = transport.GetPort ();
326  m_connected = true;
328  }
329  else
330  {
331  return -1;
332  }
333 
334  return 0;
335 }
336 
337 int
339 {
341  return -1;
342 }
343 
344 int
345 UdpSocketImpl::Send (Ptr<Packet> p, uint32_t flags)
346 {
347  NS_LOG_FUNCTION (this << p << flags);
348 
349  if (!m_connected)
350  {
352  return -1;
353  }
354 
355  return DoSend (p);
356 }
357 
358 int
360 {
361  NS_LOG_FUNCTION (this << p);
363  {
364  if (Bind () == -1)
365  {
366  NS_ASSERT (m_endPoint == 0);
367  return -1;
368  }
369  NS_ASSERT (m_endPoint != 0);
370  }
372  {
373  if (Bind6 () == -1)
374  {
375  NS_ASSERT (m_endPoint6 == 0);
376  return -1;
377  }
378  NS_ASSERT (m_endPoint6 != 0);
379  }
380  if (m_shutdownSend)
381  {
383  return -1;
384  }
385 
386  return DoSendTo (p, (const Address)m_defaultAddress);
387 }
388 
389 int
391 {
392  NS_LOG_FUNCTION (this << p << address);
393 
394  if (!m_connected)
395  {
396  NS_LOG_LOGIC ("Not connected");
397  if (InetSocketAddress::IsMatchingType(address) == true)
398  {
400  Ipv4Address ipv4 = transport.GetIpv4 ();
401  uint16_t port = transport.GetPort ();
402  return DoSendTo (p, ipv4, port);
403  }
404  else if (Inet6SocketAddress::IsMatchingType(address) == true)
405  {
407  Ipv6Address ipv6 = transport.GetIpv6 ();
408  uint16_t port = transport.GetPort ();
409  return DoSendTo (p, ipv6, port);
410  }
411  else
412  {
413  return -1;
414  }
415  }
416  else
417  {
418  // connected UDP socket must use default addresses
419  NS_LOG_LOGIC ("Connected");
421  {
423  }
425  {
427  }
428  }
430  return(-1);
431 }
432 
433 int
435 {
436  NS_LOG_FUNCTION (this << p << dest << port);
437  if (m_boundnetdevice)
438  {
439  NS_LOG_LOGIC ("Bound interface number " << m_boundnetdevice->GetIfIndex ());
440  }
441  if (m_endPoint == 0)
442  {
443  if (Bind () == -1)
444  {
445  NS_ASSERT (m_endPoint == 0);
446  return -1;
447  }
448  NS_ASSERT (m_endPoint != 0);
449  }
450  if (m_shutdownSend)
451  {
453  return -1;
454  }
455 
456  if (p->GetSize () > GetTxAvailable () )
457  {
459  return -1;
460  }
461 
462  if (IsManualIpTos ())
463  {
464  SocketIpTosTag ipTosTag;
465  ipTosTag.SetTos (GetIpTos ());
466  p->AddPacketTag (ipTosTag);
467  }
468 
469  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
470 
471  // Locally override the IP TTL for this socket
472  // We cannot directly modify the TTL at this stage, so we set a Packet tag
473  // The destination can be either multicast, unicast/anycast, or
474  // either all-hosts broadcast or limited (subnet-directed) broadcast.
475  // For the latter two broadcast types, the TTL will later be set to one
476  // irrespective of what is set in these socket options. So, this tagging
477  // may end up setting the TTL of a limited broadcast packet to be
478  // the same as a unicast, but it will be fixed further down the stack
479  if (m_ipMulticastTtl != 0 && dest.IsMulticast ())
480  {
481  SocketIpTtlTag tag;
482  tag.SetTtl (m_ipMulticastTtl);
483  p->AddPacketTag (tag);
484  }
485  else if (IsManualIpTtl () && GetIpTtl () != 0 && !dest.IsMulticast () && !dest.IsBroadcast ())
486  {
487  SocketIpTtlTag tag;
488  tag.SetTtl (GetIpTtl ());
489  p->AddPacketTag (tag);
490  }
491  {
493  bool found = p->RemovePacketTag (tag);
494  if (!found)
495  {
496  if (m_mtuDiscover)
497  {
498  tag.Enable ();
499  }
500  else
501  {
502  tag.Disable ();
503  }
504  p->AddPacketTag (tag);
505  }
506  }
507  //
508  // If dest is set to the limited broadcast address (all ones),
509  // convert it to send a copy of the packet out of every
510  // interface as a subnet-directed broadcast.
511  // Exception: if the interface has a /32 address, there is no
512  // valid subnet-directed broadcast, so send it as limited broadcast
513  // Note also that some systems will only send limited broadcast packets
514  // out of the "default" interface; here we send it out all interfaces
515  //
516  if (dest.IsBroadcast ())
517  {
518  if (!m_allowBroadcast)
519  {
521  return -1;
522  }
523  NS_LOG_LOGIC ("Limited broadcast start.");
524  for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++ )
525  {
526  // Get the primary address
527  Ipv4InterfaceAddress iaddr = ipv4->GetAddress (i, 0);
528  Ipv4Address addri = iaddr.GetLocal ();
529  if (addri == Ipv4Address ("127.0.0.1"))
530  continue;
531  // Check if interface-bound socket
532  if (m_boundnetdevice)
533  {
534  if (ipv4->GetNetDevice (i) != m_boundnetdevice)
535  continue;
536  }
537  Ipv4Mask maski = iaddr.GetMask ();
538  if (maski == Ipv4Mask::GetOnes ())
539  {
540  // if the network mask is 255.255.255.255, do not convert dest
541  NS_LOG_LOGIC ("Sending one copy from " << addri << " to " << dest
542  << " (mask is " << maski << ")");
543  m_udp->Send (p->Copy (), addri, dest,
545  NotifyDataSent (p->GetSize ());
547  }
548  else
549  {
550  // Convert to subnet-directed broadcast
551  Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski);
552  NS_LOG_LOGIC ("Sending one copy from " << addri << " to " << bcast
553  << " (mask is " << maski << ")");
554  m_udp->Send (p->Copy (), addri, bcast,
556  NotifyDataSent (p->GetSize ());
558  }
559  }
560  NS_LOG_LOGIC ("Limited broadcast end.");
561  return p->GetSize ();
562  }
564  {
565  m_udp->Send (p->Copy (), m_endPoint->GetLocalAddress (), dest,
566  m_endPoint->GetLocalPort (), port, 0);
567  NotifyDataSent (p->GetSize ());
569  return p->GetSize ();
570  }
571  else if (ipv4->GetRoutingProtocol () != 0)
572  {
573  Ipv4Header header;
574  header.SetDestination (dest);
576  Socket::SocketErrno errno_;
577  Ptr<Ipv4Route> route;
578  Ptr<NetDevice> oif = m_boundnetdevice; //specify non-zero if bound to a specific device
579  // TBD-- we could cache the route and just check its validity
580  route = ipv4->GetRoutingProtocol ()->RouteOutput (p, header, oif, errno_);
581  if (route != 0)
582  {
583  NS_LOG_LOGIC ("Route exists");
584  if (!m_allowBroadcast)
585  {
586  uint32_t outputIfIndex = ipv4->GetInterfaceForDevice (route->GetOutputDevice ());
587  uint32_t ifNAddr = ipv4->GetNAddresses (outputIfIndex);
588  for (uint32_t addrI = 0; addrI < ifNAddr; ++addrI)
589  {
590  Ipv4InterfaceAddress ifAddr = ipv4->GetAddress (outputIfIndex, addrI);
591  if (dest == ifAddr.GetBroadcast ())
592  {
594  return -1;
595  }
596  }
597  }
598 
599  header.SetSource (route->GetSource ());
600  m_udp->Send (p->Copy (), header.GetSource (), header.GetDestination (),
601  m_endPoint->GetLocalPort (), port, route);
602  NotifyDataSent (p->GetSize ());
603  return p->GetSize ();
604  }
605  else
606  {
607  NS_LOG_LOGIC ("No route to destination");
608  NS_LOG_ERROR (errno_);
609  m_errno = errno_;
610  return -1;
611  }
612  }
613  else
614  {
615  NS_LOG_ERROR ("ERROR_NOROUTETOHOST");
617  return -1;
618  }
619 
620  return 0;
621 }
622 
623 int
625 {
626  NS_LOG_FUNCTION (this << p << dest << port);
627 
628  if (dest.IsIpv4MappedAddress ())
629  {
630  return (DoSendTo(p, dest.GetIpv4MappedAddress (), port));
631  }
632  if (m_boundnetdevice)
633  {
634  NS_LOG_LOGIC ("Bound interface number " << m_boundnetdevice->GetIfIndex ());
635  }
636  if (m_endPoint6 == 0)
637  {
638  if (Bind6 () == -1)
639  {
640  NS_ASSERT (m_endPoint6 == 0);
641  return -1;
642  }
643  NS_ASSERT (m_endPoint6 != 0);
644  }
645  if (m_shutdownSend)
646  {
648  return -1;
649  }
650 
651  if (p->GetSize () > GetTxAvailable () )
652  {
654  return -1;
655  }
656 
657  if (IsManualIpv6Tclass ())
658  {
659  SocketIpv6TclassTag ipTclassTag;
660  ipTclassTag.SetTclass (GetIpv6Tclass ());
661  p->AddPacketTag (ipTclassTag);
662  }
663 
664  Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
665 
666  // Locally override the IP TTL for this socket
667  // We cannot directly modify the TTL at this stage, so we set a Packet tag
668  // The destination can be either multicast, unicast/anycast, or
669  // either all-hosts broadcast or limited (subnet-directed) broadcast.
670  // For the latter two broadcast types, the TTL will later be set to one
671  // irrespective of what is set in these socket options. So, this tagging
672  // may end up setting the TTL of a limited broadcast packet to be
673  // the same as a unicast, but it will be fixed further down the stack
674  if (m_ipMulticastTtl != 0 && dest.IsMulticast ())
675  {
678  p->AddPacketTag (tag);
679  }
680  else if (IsManualIpv6HopLimit () && GetIpv6HopLimit () != 0 && !dest.IsMulticast ())
681  {
683  tag.SetHopLimit (GetIpv6HopLimit ());
684  p->AddPacketTag (tag);
685  }
686  // There is no analgous to an IPv4 broadcast address in IPv6.
687  // Instead, we use a set of link-local, site-local, and global
688  // multicast addresses. The Ipv6 routing layers should all
689  // provide an interface-specific route to these addresses such
690  // that we can treat these multicast addresses as "not broadcast"
691 
693  {
694  m_udp->Send (p->Copy (), m_endPoint6->GetLocalAddress (), dest,
695  m_endPoint6->GetLocalPort (), port, 0);
696  NotifyDataSent (p->GetSize ());
698  return p->GetSize ();
699  }
700  else if (ipv6->GetRoutingProtocol () != 0)
701  {
702  Ipv6Header header;
703  header.SetDestinationAddress (dest);
705  Socket::SocketErrno errno_;
706  Ptr<Ipv6Route> route;
707  Ptr<NetDevice> oif = m_boundnetdevice; //specify non-zero if bound to a specific device
708  // TBD-- we could cache the route and just check its validity
709  route = ipv6->GetRoutingProtocol ()->RouteOutput (p, header, oif, errno_);
710  if (route != 0)
711  {
712  NS_LOG_LOGIC ("Route exists");
713  header.SetSourceAddress (route->GetSource ());
714  m_udp->Send (p->Copy (), header.GetSourceAddress (), header.GetDestinationAddress (),
715  m_endPoint6->GetLocalPort (), port, route);
716  NotifyDataSent (p->GetSize ());
717  return p->GetSize ();
718  }
719  else
720  {
721  NS_LOG_LOGIC ("No route to destination");
722  NS_LOG_ERROR (errno_);
723  m_errno = errno_;
724  return -1;
725  }
726  }
727  else
728  {
729  NS_LOG_ERROR ("ERROR_NOROUTETOHOST");
731  return -1;
732  }
733 
734  return 0;
735 }
736 
737 // XXX maximum message size for UDP broadcast is limited by MTU
738 // size of underlying link; we are not checking that now.
739 uint32_t
741 {
743  // No finite send buffer is modelled, but we must respect
744  // the maximum size of an IP datagram (65535 bytes - headers).
746 }
747 
748 int
749 UdpSocketImpl::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
750 {
751  NS_LOG_FUNCTION (this << p << flags << address);
752  if (InetSocketAddress::IsMatchingType (address))
753  {
754  if (IsManualIpTos ())
755  {
756  SocketIpTosTag ipTosTag;
757  ipTosTag.SetTos (GetIpTos ());
758  p->AddPacketTag (ipTosTag);
759  }
760 
762  Ipv4Address ipv4 = transport.GetIpv4 ();
763  uint16_t port = transport.GetPort ();
764  return DoSendTo (p, ipv4, port);
765  }
766  else if (Inet6SocketAddress::IsMatchingType (address))
767  {
768  if (IsManualIpv6Tclass ())
769  {
770  SocketIpv6TclassTag ipTclassTag;
771  ipTclassTag.SetTclass (GetIpv6Tclass ());
772  p->AddPacketTag (ipTclassTag);
773  }
774 
776  Ipv6Address ipv6 = transport.GetIpv6 ();
777  uint16_t port = transport.GetPort ();
778  return DoSendTo (p, ipv6, port);
779  }
780  return -1;
781 }
782 
783 uint32_t
785 {
787  // We separately maintain this state to avoid walking the queue
788  // every time this might be called
789  return m_rxAvailable;
790 }
791 
793 UdpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
794 {
795  NS_LOG_FUNCTION (this << maxSize << flags);
796  if (m_deliveryQueue.empty () )
797  {
799  return 0;
800  }
801  Ptr<Packet> p = m_deliveryQueue.front ();
802  if (p->GetSize () <= maxSize)
803  {
804  m_deliveryQueue.pop ();
805  m_rxAvailable -= p->GetSize ();
806  }
807  else
808  {
809  p = 0;
810  }
811  return p;
812 }
813 
815 UdpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags,
816  Address &fromAddress)
817 {
818  NS_LOG_FUNCTION (this << maxSize << flags);
819  Ptr<Packet> packet = Recv (maxSize, flags);
820  if (packet != 0)
821  {
822  SocketAddressTag tag;
823  bool found;
824  found = packet->PeekPacketTag (tag);
825  NS_ASSERT (found);
826  fromAddress = tag.GetAddress ();
827  }
828  return packet;
829 }
830 
831 int
833 {
835  if (m_endPoint != 0)
836  {
838  }
839  else
840  {
841  // It is possible to call this method on a socket without a name
842  // in which case, behavior is unspecified
843  address = InetSocketAddress (Ipv4Address::GetZero (), 0);
844  }
845  return 0;
846 }
847 
848 int
849 UdpSocketImpl::MulticastJoinGroup (uint32_t interface, const Address &groupAddress)
850 {
851  NS_LOG_FUNCTION (interface << groupAddress);
852  /*
853  1) sanity check interface
854  2) sanity check that it has not been called yet on this interface/group
855  3) determine address family of groupAddress
856  4) locally store a list of (interface, groupAddress)
857  5) call ipv4->MulticastJoinGroup () or Ipv6->MulticastJoinGroup ()
858  */
859  return 0;
860 }
861 
862 int
863 UdpSocketImpl::MulticastLeaveGroup (uint32_t interface, const Address &groupAddress)
864 {
865  NS_LOG_FUNCTION (interface << groupAddress);
866  /*
867  1) sanity check interface
868  2) determine address family of groupAddress
869  3) delete from local list of (interface, groupAddress); raise a LOG_WARN
870  if not already present (but return 0)
871  5) call ipv4->MulticastLeaveGroup () or Ipv6->MulticastLeaveGroup ()
872  */
873  return 0;
874 }
875 
876 void
878 {
879  NS_LOG_FUNCTION (netdevice);
880  Socket::BindToNetDevice (netdevice); // Includes sanity check
881  if (m_endPoint == 0)
882  {
883  if (Bind () == -1)
884  {
885  NS_ASSERT (m_endPoint == 0);
886  return;
887  }
888  NS_ASSERT (m_endPoint != 0);
889  }
890  m_endPoint->BindToNetDevice (netdevice);
891  return;
892 }
893 
894 void
896  Ptr<Ipv4Interface> incomingInterface)
897 {
898  NS_LOG_FUNCTION (this << packet << header << port);
899 
900  if (m_shutdownRecv)
901  {
902  return;
903  }
904 
905  // Should check via getsockopt ()..
906  if (IsRecvPktInfo ())
907  {
908  Ipv4PacketInfoTag tag;
909  packet->RemovePacketTag (tag);
910  tag.SetRecvIf (incomingInterface->GetDevice ()->GetIfIndex ());
911  packet->AddPacketTag (tag);
912  }
913 
914  //Check only version 4 options
915  if (IsIpRecvTos ())
916  {
917  SocketIpTosTag ipTosTag;
918  ipTosTag.SetTos (header.GetTos ());
919  packet->AddPacketTag (ipTosTag);
920  }
921 
922  if (IsIpRecvTtl ())
923  {
924  SocketIpTtlTag ipTtlTag;
925  ipTtlTag.SetTtl (header.GetTtl ());
926  packet->AddPacketTag (ipTtlTag);
927  }
928 
929  if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
930  {
931  Address address = InetSocketAddress (header.GetSource (), port);
932  SocketAddressTag tag;
933  tag.SetAddress (address);
934  packet->AddPacketTag (tag);
935  m_deliveryQueue.push (packet);
936  m_rxAvailable += packet->GetSize ();
937  NotifyDataRecv ();
938  }
939  else
940  {
941  // In general, this case should not occur unless the
942  // receiving application reads data from this socket slowly
943  // in comparison to the arrival rate
944  //
945  // drop and trace packet
946  NS_LOG_WARN ("No receive buffer space available. Drop.");
947  m_dropTrace (packet);
948  }
949 }
950 
951 void
953 {
954  NS_LOG_FUNCTION (this << packet << header.GetSourceAddress () << port);
955 
956  if (m_shutdownRecv)
957  {
958  return;
959  }
960 
961 
962  //Check only version 6 options
963  if (IsIpv6RecvTclass ())
964  {
965  SocketIpv6TclassTag ipTclassTag;
966  ipTclassTag.SetTclass (header.GetTrafficClass ());
967  packet->AddPacketTag (ipTclassTag);
968  }
969 
970  if (IsIpv6RecvHopLimit ())
971  {
972  SocketIpv6HopLimitTag ipHopLimitTag;
973  ipHopLimitTag.SetHopLimit (header.GetHopLimit ());
974  packet->AddPacketTag (ipHopLimitTag);
975  }
976 
977  if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
978  {
979  Address address = Inet6SocketAddress (header.GetSourceAddress (), port);
980  SocketAddressTag tag;
981  tag.SetAddress (address);
982  packet->AddPacketTag (tag);
983  m_deliveryQueue.push (packet);
984  m_rxAvailable += packet->GetSize ();
985  NotifyDataRecv ();
986  }
987  else
988  {
989  // In general, this case should not occur unless the
990  // receiving application reads data from this socket slowly
991  // in comparison to the arrival rate
992  //
993  // drop and trace packet
994  NS_LOG_WARN ("No receive buffer space available. Drop.");
995  m_dropTrace (packet);
996  }
997 }
998 
999 void
1000 UdpSocketImpl::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
1001  uint8_t icmpType, uint8_t icmpCode,
1002  uint32_t icmpInfo)
1003 {
1004  NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
1005  (uint32_t)icmpCode << icmpInfo);
1006  if (!m_icmpCallback.IsNull ())
1007  {
1008  m_icmpCallback (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1009  }
1010 }
1011 
1012 void
1013 UdpSocketImpl::ForwardIcmp6 (Ipv6Address icmpSource, uint8_t icmpTtl,
1014  uint8_t icmpType, uint8_t icmpCode,
1015  uint32_t icmpInfo)
1016 {
1017  NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
1018  (uint32_t)icmpCode << icmpInfo);
1019  if (!m_icmpCallback6.IsNull ())
1020  {
1021  m_icmpCallback6 (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
1022  }
1023 }
1024 
1025 void
1027 {
1028  m_rcvBufSize = size;
1029 }
1030 
1031 uint32_t
1033 {
1034  return m_rcvBufSize;
1035 }
1036 
1037 void
1039 {
1040  m_ipMulticastTtl = ipTtl;
1041 }
1042 
1043 uint8_t
1045 {
1046  return m_ipMulticastTtl;
1047 }
1048 
1049 void
1051 {
1052  m_ipMulticastIf = ipIf;
1053 }
1054 
1055 int32_t
1057 {
1058  return m_ipMulticastIf;
1059 }
1060 
1061 void
1063 {
1064  m_ipMulticastLoop = loop;
1065 }
1066 
1067 bool
1069 {
1070  return m_ipMulticastLoop;
1071 }
1072 
1073 void
1075 {
1076  m_mtuDiscover = discover;
1077 }
1078 bool
1080 {
1081  return m_mtuDiscover;
1082 }
1083 
1084 bool
1086 {
1087  m_allowBroadcast = allowBroadcast;
1088  return true;
1089 }
1090 
1091 bool
1093 {
1094  return m_allowBroadcast;
1095 }
1096 
1097 
1098 } // namespace ns3