PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/internet/model/udp-socket-impl.cc

https://github.com/scarletttu/ns-3-codel-dev
C++ | 1051 lines | 857 code | 82 blank | 112 comment | 182 complexity | 67acf915066dbb105f81a6e684cc6de2 MD5 | raw file
Possible License(s): GPL-2.0
  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. #include "ns3/log.h"
  21. #include "ns3/node.h"
  22. #include "ns3/inet-socket-address.h"
  23. #include "ns3/inet6-socket-address.h"
  24. #include "ns3/ipv4-route.h"
  25. #include "ns3/ipv6-route.h"
  26. #include "ns3/ipv4.h"
  27. #include "ns3/ipv6.h"
  28. #include "ns3/ipv4-header.h"
  29. #include "ns3/ipv4-routing-protocol.h"
  30. #include "ns3/ipv6-routing-protocol.h"
  31. #include "ns3/udp-socket-factory.h"
  32. #include "ns3/trace-source-accessor.h"
  33. #include "ns3/ipv4-packet-info-tag.h"
  34. #include "udp-socket-impl.h"
  35. #include "udp-l4-protocol.h"
  36. #include "ipv4-end-point.h"
  37. #include "ipv6-end-point.h"
  38. #include <limits>
  39. NS_LOG_COMPONENT_DEFINE ("UdpSocketImpl");
  40. namespace ns3 {
  41. NS_OBJECT_ENSURE_REGISTERED (UdpSocketImpl);
  42. static const uint32_t MAX_IPV4_UDP_DATAGRAM_SIZE = 65507;
  43. // Add attributes generic to all UdpSockets to base class UdpSocket
  44. TypeId
  45. UdpSocketImpl::GetTypeId (void)
  46. {
  47. static TypeId tid = TypeId ("ns3::UdpSocketImpl")
  48. .SetParent<UdpSocket> ()
  49. .AddConstructor<UdpSocketImpl> ()
  50. .AddTraceSource ("Drop", "Drop UDP packet due to receive buffer overflow",
  51. MakeTraceSourceAccessor (&UdpSocketImpl::m_dropTrace))
  52. .AddAttribute ("IcmpCallback", "Callback invoked whenever an icmp error is received on this socket.",
  53. CallbackValue (),
  54. MakeCallbackAccessor (&UdpSocketImpl::m_icmpCallback),
  55. MakeCallbackChecker ())
  56. .AddAttribute ("IcmpCallback6", "Callback invoked whenever an icmpv6 error is received on this socket.",
  57. CallbackValue (),
  58. MakeCallbackAccessor (&UdpSocketImpl::m_icmpCallback6),
  59. MakeCallbackChecker ())
  60. ;
  61. return tid;
  62. }
  63. UdpSocketImpl::UdpSocketImpl ()
  64. : m_endPoint (0),
  65. m_endPoint6 (0),
  66. m_node (0),
  67. m_udp (0),
  68. m_errno (ERROR_NOTERROR),
  69. m_shutdownSend (false),
  70. m_shutdownRecv (false),
  71. m_connected (false),
  72. m_rxAvailable (0)
  73. {
  74. NS_LOG_FUNCTION_NOARGS ();
  75. m_allowBroadcast = false;
  76. }
  77. UdpSocketImpl::~UdpSocketImpl ()
  78. {
  79. NS_LOG_FUNCTION_NOARGS ();
  80. // XXX todo: leave any multicast groups that have been joined
  81. m_node = 0;
  82. /**
  83. * Note: actually this function is called AFTER
  84. * UdpSocketImpl::Destroy or UdpSocketImpl::Destroy6
  85. * so the code below is unnecessary in normal operations
  86. */
  87. if (m_endPoint != 0)
  88. {
  89. NS_ASSERT (m_udp != 0);
  90. /**
  91. * Note that this piece of code is a bit tricky:
  92. * when DeAllocate is called, it will call into
  93. * Ipv4EndPointDemux::Deallocate which triggers
  94. * a delete of the associated endPoint which triggers
  95. * in turn a call to the method UdpSocketImpl::Destroy below
  96. * will will zero the m_endPoint field.
  97. */
  98. NS_ASSERT (m_endPoint != 0);
  99. m_udp->DeAllocate (m_endPoint);
  100. NS_ASSERT (m_endPoint == 0);
  101. }
  102. if (m_endPoint6 != 0)
  103. {
  104. NS_ASSERT (m_udp != 0);
  105. /**
  106. * Note that this piece of code is a bit tricky:
  107. * when DeAllocate is called, it will call into
  108. * Ipv4EndPointDemux::Deallocate which triggers
  109. * a delete of the associated endPoint which triggers
  110. * in turn a call to the method UdpSocketImpl::Destroy below
  111. * will will zero the m_endPoint field.
  112. */
  113. NS_ASSERT (m_endPoint6 != 0);
  114. m_udp->DeAllocate (m_endPoint6);
  115. NS_ASSERT (m_endPoint6 == 0);
  116. }
  117. m_udp = 0;
  118. }
  119. void
  120. UdpSocketImpl::SetNode (Ptr<Node> node)
  121. {
  122. NS_LOG_FUNCTION_NOARGS ();
  123. m_node = node;
  124. }
  125. void
  126. UdpSocketImpl::SetUdp (Ptr<UdpL4Protocol> udp)
  127. {
  128. NS_LOG_FUNCTION_NOARGS ();
  129. m_udp = udp;
  130. }
  131. enum Socket::SocketErrno
  132. UdpSocketImpl::GetErrno (void) const
  133. {
  134. NS_LOG_FUNCTION_NOARGS ();
  135. return m_errno;
  136. }
  137. enum Socket::SocketType
  138. UdpSocketImpl::GetSocketType (void) const
  139. {
  140. return NS3_SOCK_DGRAM;
  141. }
  142. Ptr<Node>
  143. UdpSocketImpl::GetNode (void) const
  144. {
  145. NS_LOG_FUNCTION_NOARGS ();
  146. return m_node;
  147. }
  148. void
  149. UdpSocketImpl::Destroy (void)
  150. {
  151. NS_LOG_FUNCTION_NOARGS ();
  152. m_endPoint = 0;
  153. }
  154. void
  155. UdpSocketImpl::Destroy6 (void)
  156. {
  157. NS_LOG_FUNCTION_NOARGS ();
  158. m_endPoint6 = 0;
  159. }
  160. int
  161. UdpSocketImpl::FinishBind (void)
  162. {
  163. NS_LOG_FUNCTION_NOARGS ();
  164. bool done = false;
  165. if (m_endPoint != 0)
  166. {
  167. m_endPoint->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp, Ptr<UdpSocketImpl> (this)));
  168. m_endPoint->SetIcmpCallback (MakeCallback (&UdpSocketImpl::ForwardIcmp, Ptr<UdpSocketImpl> (this)));
  169. m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy, Ptr<UdpSocketImpl> (this)));
  170. done = true;
  171. }
  172. if (m_endPoint6 != 0)
  173. {
  174. m_endPoint6->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp6, Ptr<UdpSocketImpl> (this)));
  175. m_endPoint6->SetIcmpCallback (MakeCallback (&UdpSocketImpl::ForwardIcmp6, Ptr<UdpSocketImpl> (this)));
  176. m_endPoint6->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy6, Ptr<UdpSocketImpl> (this)));
  177. done = true;
  178. }
  179. if (done)
  180. {
  181. return 0;
  182. }
  183. return -1;
  184. }
  185. int
  186. UdpSocketImpl::Bind (void)
  187. {
  188. NS_LOG_FUNCTION_NOARGS ();
  189. m_endPoint = m_udp->Allocate ();
  190. return FinishBind ();
  191. }
  192. int
  193. UdpSocketImpl::Bind6 (void)
  194. {
  195. NS_LOG_FUNCTION_NOARGS ();
  196. m_endPoint6 = m_udp->Allocate6 ();
  197. return FinishBind ();
  198. }
  199. int
  200. UdpSocketImpl::Bind (const Address &address)
  201. {
  202. NS_LOG_FUNCTION (this << address);
  203. if (InetSocketAddress::IsMatchingType (address))
  204. {
  205. InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
  206. Ipv4Address ipv4 = transport.GetIpv4 ();
  207. uint16_t port = transport.GetPort ();
  208. if (ipv4 == Ipv4Address::GetAny () && port == 0)
  209. {
  210. m_endPoint = m_udp->Allocate ();
  211. }
  212. else if (ipv4 == Ipv4Address::GetAny () && port != 0)
  213. {
  214. m_endPoint = m_udp->Allocate (port);
  215. }
  216. else if (ipv4 != Ipv4Address::GetAny () && port == 0)
  217. {
  218. m_endPoint = m_udp->Allocate (ipv4);
  219. }
  220. else if (ipv4 != Ipv4Address::GetAny () && port != 0)
  221. {
  222. m_endPoint = m_udp->Allocate (ipv4, port);
  223. }
  224. }
  225. else if (Inet6SocketAddress::IsMatchingType (address))
  226. {
  227. Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
  228. Ipv6Address ipv6 = transport.GetIpv6 ();
  229. uint16_t port = transport.GetPort ();
  230. if (ipv6 == Ipv6Address::GetAny () && port == 0)
  231. {
  232. m_endPoint6 = m_udp->Allocate6 ();
  233. }
  234. else if (ipv6 == Ipv6Address::GetAny () && port != 0)
  235. {
  236. m_endPoint6 = m_udp->Allocate6 (port);
  237. }
  238. else if (ipv6 != Ipv6Address::GetAny () && port == 0)
  239. {
  240. m_endPoint6 = m_udp->Allocate6 (ipv6);
  241. }
  242. else if (ipv6 != Ipv6Address::GetAny () && port != 0)
  243. {
  244. m_endPoint6 = m_udp->Allocate6 (ipv6, port);
  245. }
  246. }
  247. else
  248. {
  249. NS_LOG_ERROR ("Not IsMatchingType");
  250. m_errno = ERROR_INVAL;
  251. return -1;
  252. }
  253. return FinishBind ();
  254. }
  255. int
  256. UdpSocketImpl::ShutdownSend (void)
  257. {
  258. NS_LOG_FUNCTION_NOARGS ();
  259. m_shutdownSend = true;
  260. return 0;
  261. }
  262. int
  263. UdpSocketImpl::ShutdownRecv (void)
  264. {
  265. NS_LOG_FUNCTION_NOARGS ();
  266. m_shutdownRecv = true;
  267. return 0;
  268. }
  269. int
  270. UdpSocketImpl::Close (void)
  271. {
  272. NS_LOG_FUNCTION_NOARGS ();
  273. if (m_shutdownRecv == true && m_shutdownSend == true)
  274. {
  275. m_errno = Socket::ERROR_BADF;
  276. return -1;
  277. }
  278. m_shutdownRecv = true;
  279. m_shutdownSend = true;
  280. return 0;
  281. }
  282. int
  283. UdpSocketImpl::Connect (const Address & address)
  284. {
  285. NS_LOG_FUNCTION (this << address);
  286. if (InetSocketAddress::IsMatchingType(address) == true)
  287. {
  288. InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
  289. m_defaultAddress = Address(transport.GetIpv4 ());
  290. m_defaultPort = transport.GetPort ();
  291. m_connected = true;
  292. NotifyConnectionSucceeded ();
  293. }
  294. else if (Inet6SocketAddress::IsMatchingType(address) == true)
  295. {
  296. Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
  297. m_defaultAddress = Address(transport.GetIpv6 ());
  298. m_defaultPort = transport.GetPort ();
  299. m_connected = true;
  300. NotifyConnectionSucceeded ();
  301. }
  302. else
  303. {
  304. return -1;
  305. }
  306. return 0;
  307. }
  308. int
  309. UdpSocketImpl::Listen (void)
  310. {
  311. m_errno = Socket::ERROR_OPNOTSUPP;
  312. return -1;
  313. }
  314. int
  315. UdpSocketImpl::Send (Ptr<Packet> p, uint32_t flags)
  316. {
  317. NS_LOG_FUNCTION (this << p << flags);
  318. if (!m_connected)
  319. {
  320. m_errno = ERROR_NOTCONN;
  321. return -1;
  322. }
  323. return DoSend (p);
  324. }
  325. int
  326. UdpSocketImpl::DoSend (Ptr<Packet> p)
  327. {
  328. NS_LOG_FUNCTION (this << p);
  329. if ((m_endPoint == 0) && (InetSocketAddress::IsMatchingType(m_defaultAddress) == true))
  330. {
  331. if (Bind () == -1)
  332. {
  333. NS_ASSERT (m_endPoint == 0);
  334. return -1;
  335. }
  336. NS_ASSERT (m_endPoint != 0);
  337. }
  338. else if ((m_endPoint6 == 0) && (Inet6SocketAddress::IsMatchingType(m_defaultAddress) == true))
  339. {
  340. if (Bind6 () == -1)
  341. {
  342. NS_ASSERT (m_endPoint6 == 0);
  343. return -1;
  344. }
  345. NS_ASSERT (m_endPoint6 != 0);
  346. }
  347. if (m_shutdownSend)
  348. {
  349. m_errno = ERROR_SHUTDOWN;
  350. return -1;
  351. }
  352. return DoSendTo (p, (const Address)m_defaultAddress);
  353. }
  354. int
  355. UdpSocketImpl::DoSendTo (Ptr<Packet> p, const Address &address)
  356. {
  357. NS_LOG_FUNCTION (this << p << address);
  358. if (!m_connected)
  359. {
  360. NS_LOG_LOGIC ("Not connected");
  361. if (InetSocketAddress::IsMatchingType(address) == true)
  362. {
  363. InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
  364. Ipv4Address ipv4 = transport.GetIpv4 ();
  365. uint16_t port = transport.GetPort ();
  366. return DoSendTo (p, ipv4, port);
  367. }
  368. else if (Inet6SocketAddress::IsMatchingType(address) == true)
  369. {
  370. Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
  371. Ipv6Address ipv6 = transport.GetIpv6 ();
  372. uint16_t port = transport.GetPort ();
  373. return DoSendTo (p, ipv6, port);
  374. }
  375. else
  376. {
  377. return -1;
  378. }
  379. }
  380. else
  381. {
  382. // connected UDP socket must use default addresses
  383. NS_LOG_LOGIC ("Connected");
  384. if (Ipv4Address::IsMatchingType(m_defaultAddress))
  385. {
  386. return DoSendTo (p, Ipv4Address::ConvertFrom(m_defaultAddress), m_defaultPort);
  387. }
  388. else if (Ipv6Address::IsMatchingType(m_defaultAddress))
  389. {
  390. return DoSendTo (p, Ipv6Address::ConvertFrom(m_defaultAddress), m_defaultPort);
  391. }
  392. }
  393. m_errno = ERROR_AFNOSUPPORT;
  394. return(-1);
  395. }
  396. int
  397. UdpSocketImpl::DoSendTo (Ptr<Packet> p, Ipv4Address dest, uint16_t port)
  398. {
  399. NS_LOG_FUNCTION (this << p << dest << port);
  400. if (m_boundnetdevice)
  401. {
  402. NS_LOG_LOGIC ("Bound interface number " << m_boundnetdevice->GetIfIndex ());
  403. }
  404. if (m_endPoint == 0)
  405. {
  406. if (Bind () == -1)
  407. {
  408. NS_ASSERT (m_endPoint == 0);
  409. return -1;
  410. }
  411. NS_ASSERT (m_endPoint != 0);
  412. }
  413. if (m_shutdownSend)
  414. {
  415. m_errno = ERROR_SHUTDOWN;
  416. return -1;
  417. }
  418. if (p->GetSize () > GetTxAvailable () )
  419. {
  420. m_errno = ERROR_MSGSIZE;
  421. return -1;
  422. }
  423. Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
  424. // Locally override the IP TTL for this socket
  425. // We cannot directly modify the TTL at this stage, so we set a Packet tag
  426. // The destination can be either multicast, unicast/anycast, or
  427. // either all-hosts broadcast or limited (subnet-directed) broadcast.
  428. // For the latter two broadcast types, the TTL will later be set to one
  429. // irrespective of what is set in these socket options. So, this tagging
  430. // may end up setting the TTL of a limited broadcast packet to be
  431. // the same as a unicast, but it will be fixed further down the stack
  432. if (m_ipMulticastTtl != 0 && dest.IsMulticast ())
  433. {
  434. SocketIpTtlTag tag;
  435. tag.SetTtl (m_ipMulticastTtl);
  436. p->AddPacketTag (tag);
  437. }
  438. else if (m_ipTtl != 0 && !dest.IsMulticast () && !dest.IsBroadcast ())
  439. {
  440. SocketIpTtlTag tag;
  441. tag.SetTtl (m_ipTtl);
  442. p->AddPacketTag (tag);
  443. }
  444. {
  445. SocketSetDontFragmentTag tag;
  446. bool found = p->RemovePacketTag (tag);
  447. if (!found)
  448. {
  449. if (m_mtuDiscover)
  450. {
  451. tag.Enable ();
  452. }
  453. else
  454. {
  455. tag.Disable ();
  456. }
  457. p->AddPacketTag (tag);
  458. }
  459. }
  460. //
  461. // If dest is set to the limited broadcast address (all ones),
  462. // convert it to send a copy of the packet out of every
  463. // interface as a subnet-directed broadcast.
  464. // Exception: if the interface has a /32 address, there is no
  465. // valid subnet-directed broadcast, so send it as limited broadcast
  466. // Note also that some systems will only send limited broadcast packets
  467. // out of the "default" interface; here we send it out all interfaces
  468. //
  469. if (dest.IsBroadcast ())
  470. {
  471. if (!m_allowBroadcast)
  472. {
  473. m_errno = ERROR_OPNOTSUPP;
  474. return -1;
  475. }
  476. NS_LOG_LOGIC ("Limited broadcast start.");
  477. for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++ )
  478. {
  479. // Get the primary address
  480. Ipv4InterfaceAddress iaddr = ipv4->GetAddress (i, 0);
  481. Ipv4Address addri = iaddr.GetLocal ();
  482. if (addri == Ipv4Address ("127.0.0.1"))
  483. continue;
  484. // Check if interface-bound socket
  485. if (m_boundnetdevice)
  486. {
  487. if (ipv4->GetNetDevice (i) != m_boundnetdevice)
  488. continue;
  489. }
  490. Ipv4Mask maski = iaddr.GetMask ();
  491. if (maski == Ipv4Mask::GetOnes ())
  492. {
  493. // if the network mask is 255.255.255.255, do not convert dest
  494. NS_LOG_LOGIC ("Sending one copy from " << addri << " to " << dest
  495. << " (mask is " << maski << ")");
  496. m_udp->Send (p->Copy (), addri, dest,
  497. m_endPoint->GetLocalPort (), port);
  498. NotifyDataSent (p->GetSize ());
  499. NotifySend (GetTxAvailable ());
  500. }
  501. else
  502. {
  503. // Convert to subnet-directed broadcast
  504. Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski);
  505. NS_LOG_LOGIC ("Sending one copy from " << addri << " to " << bcast
  506. << " (mask is " << maski << ")");
  507. m_udp->Send (p->Copy (), addri, bcast,
  508. m_endPoint->GetLocalPort (), port);
  509. NotifyDataSent (p->GetSize ());
  510. NotifySend (GetTxAvailable ());
  511. }
  512. }
  513. NS_LOG_LOGIC ("Limited broadcast end.");
  514. return p->GetSize ();
  515. }
  516. else if (m_endPoint->GetLocalAddress () != Ipv4Address::GetAny ())
  517. {
  518. m_udp->Send (p->Copy (), m_endPoint->GetLocalAddress (), dest,
  519. m_endPoint->GetLocalPort (), port, 0);
  520. NotifyDataSent (p->GetSize ());
  521. NotifySend (GetTxAvailable ());
  522. return p->GetSize ();
  523. }
  524. else if (ipv4->GetRoutingProtocol () != 0)
  525. {
  526. Ipv4Header header;
  527. header.SetDestination (dest);
  528. header.SetProtocol (UdpL4Protocol::PROT_NUMBER);
  529. Socket::SocketErrno errno_;
  530. Ptr<Ipv4Route> route;
  531. Ptr<NetDevice> oif = m_boundnetdevice; //specify non-zero if bound to a specific device
  532. // TBD-- we could cache the route and just check its validity
  533. route = ipv4->GetRoutingProtocol ()->RouteOutput (p, header, oif, errno_);
  534. if (route != 0)
  535. {
  536. NS_LOG_LOGIC ("Route exists");
  537. if (!m_allowBroadcast)
  538. {
  539. uint32_t outputIfIndex = ipv4->GetInterfaceForDevice (route->GetOutputDevice ());
  540. uint32_t ifNAddr = ipv4->GetNAddresses (outputIfIndex);
  541. for (uint32_t addrI = 0; addrI < ifNAddr; ++addrI)
  542. {
  543. Ipv4InterfaceAddress ifAddr = ipv4->GetAddress (outputIfIndex, addrI);
  544. if (dest == ifAddr.GetBroadcast ())
  545. {
  546. m_errno = ERROR_OPNOTSUPP;
  547. return -1;
  548. }
  549. }
  550. }
  551. header.SetSource (route->GetSource ());
  552. m_udp->Send (p->Copy (), header.GetSource (), header.GetDestination (),
  553. m_endPoint->GetLocalPort (), port, route);
  554. NotifyDataSent (p->GetSize ());
  555. return p->GetSize ();
  556. }
  557. else
  558. {
  559. NS_LOG_LOGIC ("No route to destination");
  560. NS_LOG_ERROR (errno_);
  561. m_errno = errno_;
  562. return -1;
  563. }
  564. }
  565. else
  566. {
  567. NS_LOG_ERROR ("ERROR_NOROUTETOHOST");
  568. m_errno = ERROR_NOROUTETOHOST;
  569. return -1;
  570. }
  571. return 0;
  572. }
  573. int
  574. UdpSocketImpl::DoSendTo (Ptr<Packet> p, Ipv6Address dest, uint16_t port)
  575. {
  576. NS_LOG_FUNCTION (this << p << dest << port);
  577. if (dest.IsIpv4MappedAddress ())
  578. {
  579. return (DoSendTo(p, dest.GetIpv4MappedAddress (), port));
  580. }
  581. if (m_boundnetdevice)
  582. {
  583. NS_LOG_LOGIC ("Bound interface number " << m_boundnetdevice->GetIfIndex ());
  584. }
  585. if (m_endPoint6 == 0)
  586. {
  587. if (Bind6 () == -1)
  588. {
  589. NS_ASSERT (m_endPoint6 == 0);
  590. return -1;
  591. }
  592. NS_ASSERT (m_endPoint6 != 0);
  593. }
  594. if (m_shutdownSend)
  595. {
  596. m_errno = ERROR_SHUTDOWN;
  597. return -1;
  598. }
  599. if (p->GetSize () > GetTxAvailable () )
  600. {
  601. m_errno = ERROR_MSGSIZE;
  602. return -1;
  603. }
  604. Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
  605. // Locally override the IP TTL for this socket
  606. // We cannot directly modify the TTL at this stage, so we set a Packet tag
  607. // The destination can be either multicast, unicast/anycast, or
  608. // either all-hosts broadcast or limited (subnet-directed) broadcast.
  609. // For the latter two broadcast types, the TTL will later be set to one
  610. // irrespective of what is set in these socket options. So, this tagging
  611. // may end up setting the TTL of a limited broadcast packet to be
  612. // the same as a unicast, but it will be fixed further down the stack
  613. if (m_ipMulticastTtl != 0 && dest.IsMulticast ())
  614. {
  615. SocketIpTtlTag tag;
  616. tag.SetTtl (m_ipMulticastTtl);
  617. p->AddPacketTag (tag);
  618. }
  619. else if (m_ipTtl != 0 && !dest.IsMulticast ())
  620. {
  621. SocketIpTtlTag tag;
  622. tag.SetTtl (m_ipTtl);
  623. p->AddPacketTag (tag);
  624. }
  625. // There is no analgous to an IPv4 broadcast address in IPv6.
  626. // Instead, we use a set of link-local, site-local, and global
  627. // multicast addresses. The Ipv6 routing layers should all
  628. // provide an interface-specific route to these addresses such
  629. // that we can treat these multicast addresses as "not broadcast"
  630. if (m_endPoint6->GetLocalAddress () != Ipv6Address::GetAny ())
  631. {
  632. m_udp->Send (p->Copy (), m_endPoint6->GetLocalAddress (), dest,
  633. m_endPoint6->GetLocalPort (), port, 0);
  634. NotifyDataSent (p->GetSize ());
  635. NotifySend (GetTxAvailable ());
  636. return p->GetSize ();
  637. }
  638. else if (ipv6->GetRoutingProtocol () != 0)
  639. {
  640. Ipv6Header header;
  641. header.SetDestinationAddress (dest);
  642. header.SetNextHeader (UdpL4Protocol::PROT_NUMBER);
  643. Socket::SocketErrno errno_;
  644. Ptr<Ipv6Route> route;
  645. Ptr<NetDevice> oif = m_boundnetdevice; //specify non-zero if bound to a specific device
  646. // TBD-- we could cache the route and just check its validity
  647. route = ipv6->GetRoutingProtocol ()->RouteOutput (p, header, oif, errno_);
  648. if (route != 0)
  649. {
  650. NS_LOG_LOGIC ("Route exists");
  651. header.SetSourceAddress (route->GetSource ());
  652. m_udp->Send (p->Copy (), header.GetSourceAddress (), header.GetDestinationAddress (),
  653. m_endPoint6->GetLocalPort (), port, route);
  654. NotifyDataSent (p->GetSize ());
  655. return p->GetSize ();
  656. }
  657. else
  658. {
  659. NS_LOG_LOGIC ("No route to destination");
  660. NS_LOG_ERROR (errno_);
  661. m_errno = errno_;
  662. return -1;
  663. }
  664. }
  665. else
  666. {
  667. NS_LOG_ERROR ("ERROR_NOROUTETOHOST");
  668. m_errno = ERROR_NOROUTETOHOST;
  669. return -1;
  670. }
  671. return 0;
  672. }
  673. // XXX maximum message size for UDP broadcast is limited by MTU
  674. // size of underlying link; we are not checking that now.
  675. uint32_t
  676. UdpSocketImpl::GetTxAvailable (void) const
  677. {
  678. NS_LOG_FUNCTION_NOARGS ();
  679. // No finite send buffer is modelled, but we must respect
  680. // the maximum size of an IP datagram (65535 bytes - headers).
  681. return MAX_IPV4_UDP_DATAGRAM_SIZE;
  682. }
  683. int
  684. UdpSocketImpl::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
  685. {
  686. NS_LOG_FUNCTION (this << p << flags << address);
  687. if (InetSocketAddress::IsMatchingType (address))
  688. {
  689. InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
  690. Ipv4Address ipv4 = transport.GetIpv4 ();
  691. uint16_t port = transport.GetPort ();
  692. return DoSendTo (p, ipv4, port);
  693. }
  694. else if (Inet6SocketAddress::IsMatchingType (address))
  695. {
  696. Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
  697. Ipv6Address ipv6 = transport.GetIpv6 ();
  698. uint16_t port = transport.GetPort ();
  699. return DoSendTo (p, ipv6, port);
  700. }
  701. return -1;
  702. }
  703. uint32_t
  704. UdpSocketImpl::GetRxAvailable (void) const
  705. {
  706. NS_LOG_FUNCTION_NOARGS ();
  707. // We separately maintain this state to avoid walking the queue
  708. // every time this might be called
  709. return m_rxAvailable;
  710. }
  711. Ptr<Packet>
  712. UdpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
  713. {
  714. NS_LOG_FUNCTION (this << maxSize << flags);
  715. if (m_deliveryQueue.empty () )
  716. {
  717. m_errno = ERROR_AGAIN;
  718. return 0;
  719. }
  720. Ptr<Packet> p = m_deliveryQueue.front ();
  721. if (p->GetSize () <= maxSize)
  722. {
  723. m_deliveryQueue.pop ();
  724. m_rxAvailable -= p->GetSize ();
  725. }
  726. else
  727. {
  728. p = 0;
  729. }
  730. return p;
  731. }
  732. Ptr<Packet>
  733. UdpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags,
  734. Address &fromAddress)
  735. {
  736. NS_LOG_FUNCTION (this << maxSize << flags);
  737. Ptr<Packet> packet = Recv (maxSize, flags);
  738. if (packet != 0)
  739. {
  740. SocketAddressTag tag;
  741. bool found;
  742. found = packet->PeekPacketTag (tag);
  743. NS_ASSERT (found);
  744. fromAddress = tag.GetAddress ();
  745. }
  746. return packet;
  747. }
  748. int
  749. UdpSocketImpl::GetSockName (Address &address) const
  750. {
  751. NS_LOG_FUNCTION_NOARGS ();
  752. if (m_endPoint != 0)
  753. {
  754. address = InetSocketAddress (m_endPoint->GetLocalAddress (), m_endPoint->GetLocalPort ());
  755. }
  756. else
  757. {
  758. // It is possible to call this method on a socket without a name
  759. // in which case, behavior is unspecified
  760. address = InetSocketAddress (Ipv4Address::GetZero (), 0);
  761. }
  762. return 0;
  763. }
  764. int
  765. UdpSocketImpl::MulticastJoinGroup (uint32_t interface, const Address &groupAddress)
  766. {
  767. NS_LOG_FUNCTION (interface << groupAddress);
  768. /*
  769. 1) sanity check interface
  770. 2) sanity check that it has not been called yet on this interface/group
  771. 3) determine address family of groupAddress
  772. 4) locally store a list of (interface, groupAddress)
  773. 5) call ipv4->MulticastJoinGroup () or Ipv6->MulticastJoinGroup ()
  774. */
  775. return 0;
  776. }
  777. int
  778. UdpSocketImpl::MulticastLeaveGroup (uint32_t interface, const Address &groupAddress)
  779. {
  780. NS_LOG_FUNCTION (interface << groupAddress);
  781. /*
  782. 1) sanity check interface
  783. 2) determine address family of groupAddress
  784. 3) delete from local list of (interface, groupAddress); raise a LOG_WARN
  785. if not already present (but return 0)
  786. 5) call ipv4->MulticastLeaveGroup () or Ipv6->MulticastLeaveGroup ()
  787. */
  788. return 0;
  789. }
  790. void
  791. UdpSocketImpl::BindToNetDevice (Ptr<NetDevice> netdevice)
  792. {
  793. NS_LOG_FUNCTION (netdevice);
  794. Socket::BindToNetDevice (netdevice); // Includes sanity check
  795. if (m_endPoint == 0)
  796. {
  797. if (Bind () == -1)
  798. {
  799. NS_ASSERT (m_endPoint == 0);
  800. return;
  801. }
  802. NS_ASSERT (m_endPoint != 0);
  803. }
  804. m_endPoint->BindToNetDevice (netdevice);
  805. return;
  806. }
  807. void
  808. UdpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Header header, uint16_t port,
  809. Ptr<Ipv4Interface> incomingInterface)
  810. {
  811. NS_LOG_FUNCTION (this << packet << header << port);
  812. if (m_shutdownRecv)
  813. {
  814. return;
  815. }
  816. // Should check via getsockopt ()..
  817. if (IsRecvPktInfo ())
  818. {
  819. Ipv4PacketInfoTag tag;
  820. packet->RemovePacketTag (tag);
  821. tag.SetRecvIf (incomingInterface->GetDevice ()->GetIfIndex ());
  822. packet->AddPacketTag (tag);
  823. }
  824. if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
  825. {
  826. Address address = InetSocketAddress (header.GetSource (), port);
  827. SocketAddressTag tag;
  828. tag.SetAddress (address);
  829. packet->AddPacketTag (tag);
  830. m_deliveryQueue.push (packet);
  831. m_rxAvailable += packet->GetSize ();
  832. NotifyDataRecv ();
  833. }
  834. else
  835. {
  836. // In general, this case should not occur unless the
  837. // receiving application reads data from this socket slowly
  838. // in comparison to the arrival rate
  839. //
  840. // drop and trace packet
  841. NS_LOG_WARN ("No receive buffer space available. Drop.");
  842. m_dropTrace (packet);
  843. }
  844. }
  845. void
  846. UdpSocketImpl::ForwardUp6 (Ptr<Packet> packet, Ipv6Address saddr, Ipv6Address daddr, uint16_t port)
  847. {
  848. NS_LOG_FUNCTION (this << packet << saddr << port);
  849. if (m_shutdownRecv)
  850. {
  851. return;
  852. }
  853. if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
  854. {
  855. Address address = Inet6SocketAddress (saddr, port);
  856. SocketAddressTag tag;
  857. tag.SetAddress (address);
  858. packet->AddPacketTag (tag);
  859. m_deliveryQueue.push (packet);
  860. m_rxAvailable += packet->GetSize ();
  861. NotifyDataRecv ();
  862. }
  863. else
  864. {
  865. // In general, this case should not occur unless the
  866. // receiving application reads data from this socket slowly
  867. // in comparison to the arrival rate
  868. //
  869. // drop and trace packet
  870. NS_LOG_WARN ("No receive buffer space available. Drop.");
  871. m_dropTrace (packet);
  872. }
  873. }
  874. void
  875. UdpSocketImpl::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
  876. uint8_t icmpType, uint8_t icmpCode,
  877. uint32_t icmpInfo)
  878. {
  879. NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
  880. (uint32_t)icmpCode << icmpInfo);
  881. if (!m_icmpCallback.IsNull ())
  882. {
  883. m_icmpCallback (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
  884. }
  885. }
  886. void
  887. UdpSocketImpl::ForwardIcmp6 (Ipv6Address icmpSource, uint8_t icmpTtl,
  888. uint8_t icmpType, uint8_t icmpCode,
  889. uint32_t icmpInfo)
  890. {
  891. NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
  892. (uint32_t)icmpCode << icmpInfo);
  893. if (!m_icmpCallback6.IsNull ())
  894. {
  895. m_icmpCallback6 (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
  896. }
  897. }
  898. void
  899. UdpSocketImpl::SetRcvBufSize (uint32_t size)
  900. {
  901. m_rcvBufSize = size;
  902. }
  903. uint32_t
  904. UdpSocketImpl::GetRcvBufSize (void) const
  905. {
  906. return m_rcvBufSize;
  907. }
  908. void
  909. UdpSocketImpl::SetIpTtl (uint8_t ipTtl)
  910. {
  911. m_ipTtl = ipTtl;
  912. }
  913. uint8_t
  914. UdpSocketImpl::GetIpTtl (void) const
  915. {
  916. return m_ipTtl;
  917. }
  918. void
  919. UdpSocketImpl::SetIpMulticastTtl (uint8_t ipTtl)
  920. {
  921. m_ipMulticastTtl = ipTtl;
  922. }
  923. uint8_t
  924. UdpSocketImpl::GetIpMulticastTtl (void) const
  925. {
  926. return m_ipMulticastTtl;
  927. }
  928. void
  929. UdpSocketImpl::SetIpMulticastIf (int32_t ipIf)
  930. {
  931. m_ipMulticastIf = ipIf;
  932. }
  933. int32_t
  934. UdpSocketImpl::GetIpMulticastIf (void) const
  935. {
  936. return m_ipMulticastIf;
  937. }
  938. void
  939. UdpSocketImpl::SetIpMulticastLoop (bool loop)
  940. {
  941. m_ipMulticastLoop = loop;
  942. }
  943. bool
  944. UdpSocketImpl::GetIpMulticastLoop (void) const
  945. {
  946. return m_ipMulticastLoop;
  947. }
  948. void
  949. UdpSocketImpl::SetMtuDiscover (bool discover)
  950. {
  951. m_mtuDiscover = discover;
  952. }
  953. bool
  954. UdpSocketImpl::GetMtuDiscover (void) const
  955. {
  956. return m_mtuDiscover;
  957. }
  958. bool
  959. UdpSocketImpl::SetAllowBroadcast (bool allowBroadcast)
  960. {
  961. m_allowBroadcast = allowBroadcast;
  962. return true;
  963. }
  964. bool
  965. UdpSocketImpl::GetAllowBroadcast () const
  966. {
  967. return m_allowBroadcast;
  968. }
  969. } // namespace ns3