udp_send.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /****************************************************************************
  2. * net/udp/udp_send.c
  3. *
  4. * Copyright (C) 2007-2009, 2011, 2015 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Adapted for NuttX from logic in uIP which also has a BSD-like license:
  8. *
  9. * Original author Adam Dunkels <adam@dunkels.com>
  10. * Copyright () 2001-2003, Adam Dunkels.
  11. * All rights reserved.
  12. *
  13. * Redistribution and use in source and binary forms, with or without
  14. * modification, are permitted provided that the following conditions
  15. * are met:
  16. *
  17. * 1. Redistributions of source code must retain the above copyright
  18. * notice, this list of conditions and the following disclaimer.
  19. * 2. Redistributions in binary form must reproduce the above copyright
  20. * notice, this list of conditions and the following disclaimer in the
  21. * documentation and/or other materials provided with the distribution.
  22. * 3. The name of the author may not be used to endorse or promote
  23. * products derived from this software without specific prior
  24. * written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
  27. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  28. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  30. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  32. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  34. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  35. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  36. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. ****************************************************************************/
  39. /****************************************************************************
  40. * Included Files
  41. ****************************************************************************/
  42. #include <nuttx/config.h>
  43. #if defined(CONFIG_NET) && defined(CONFIG_NET_UDP)
  44. #include <string.h>
  45. #include <debug.h>
  46. #include <assert.h>
  47. #include <arpa/inet.h>
  48. #include <nuttx/net/netconfig.h>
  49. #include <nuttx/net/netdev.h>
  50. #include <nuttx/net/netstats.h>
  51. #include <nuttx/net/ip.h>
  52. #include <nuttx/net/udp.h>
  53. #include "devif/devif.h"
  54. #include "inet/inet.h"
  55. #include "utils/utils.h"
  56. #include "udp/udp.h"
  57. /****************************************************************************
  58. * Pre-processor Definitions
  59. ****************************************************************************/
  60. #define IPv4BUF \
  61. ((struct ipv4_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
  62. #define IPv6BUF \
  63. ((struct ipv6_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
  64. #define UDPIPv4BUF \
  65. ((struct udp_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev) + IPv4_HDRLEN])
  66. #define UDPIPv6BUF \
  67. ((struct udp_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev) + IPv6_HDRLEN])
  68. /****************************************************************************
  69. * Public Functions
  70. ****************************************************************************/
  71. /****************************************************************************
  72. * Name: udp_send
  73. *
  74. * Description:
  75. * Set-up to send a UDP packet
  76. *
  77. * Input Parameters:
  78. * dev - The device driver structure to use in the send operation
  79. * conn - The UDP "connection" structure holding port information
  80. *
  81. * Returned Value:
  82. * None
  83. *
  84. * Assumptions:
  85. * The network is locked.
  86. *
  87. ****************************************************************************/
  88. void udp_send(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn)
  89. {
  90. FAR struct udp_hdr_s *udp;
  91. ninfo("UDP payload: %d (%d) bytes\n", dev->d_sndlen, dev->d_len);
  92. if (dev->d_sndlen > 0)
  93. {
  94. /* Initialize the IP header. */
  95. #ifdef CONFIG_NET_IPv4
  96. #ifdef CONFIG_NET_IPv6
  97. if (conn->domain == PF_INET ||
  98. (conn->domain == PF_INET6 &&
  99. ip6_is_ipv4addr((FAR struct in6_addr *)conn->u.ipv6.raddr)))
  100. #endif
  101. {
  102. /* Get pointers to the IPv4 header and the offset UDP header */
  103. FAR struct ipv4_hdr_s *ipv4 = IPv4BUF;
  104. DEBUGASSERT(IFF_IS_IPv4(dev->d_flags));
  105. udp = UDPIPv4BUF;
  106. /* Initialize the IPv4 header. */
  107. ipv4->vhl = 0x45;
  108. ipv4->tos = 0;
  109. ++g_ipid;
  110. ipv4->ipid[0] = g_ipid >> 8;
  111. ipv4->ipid[1] = g_ipid & 0xff;
  112. ipv4->ipoffset[0] = 0;
  113. ipv4->ipoffset[1] = 0;
  114. ipv4->ttl = conn->ttl;
  115. ipv4->proto = IP_PROTO_UDP;
  116. net_ipv4addr_hdrcopy(ipv4->srcipaddr, &dev->d_ipaddr);
  117. #ifdef CONFIG_NET_IPv6
  118. if (conn->domain == PF_INET6 &&
  119. ip6_is_ipv4addr((FAR struct in6_addr *)conn->u.ipv6.raddr))
  120. {
  121. in_addr_t raddr = ip6_get_ipv4addr((FAR struct in6_addr *)conn->u.ipv6.raddr);
  122. net_ipv4addr_hdrcopy(ipv4->destipaddr, &raddr);
  123. }
  124. else
  125. #endif
  126. {
  127. net_ipv4addr_hdrcopy(ipv4->destipaddr, &conn->u.ipv4.raddr);
  128. }
  129. /* The total length to send is the size of the application data
  130. * plus the IPv4 and UDP headers (and, eventually, the link layer
  131. * header)
  132. */
  133. dev->d_len = dev->d_sndlen + IPv4UDP_HDRLEN;
  134. /* The IPv4 length includes the size of the IPv4 header */
  135. ipv4->len[0] = (dev->d_len >> 8);
  136. ipv4->len[1] = (dev->d_len & 0xff);
  137. /* Calculate IP checksum. */
  138. ipv4->ipchksum = 0;
  139. ipv4->ipchksum = ~ipv4_chksum(dev);
  140. #ifdef CONFIG_NET_STATISTICS
  141. g_netstats.ipv4.sent++;
  142. #endif
  143. }
  144. #endif /* CONFIG_NET_IPv4 */
  145. #ifdef CONFIG_NET_IPv6
  146. #ifdef CONFIG_NET_IPv4
  147. else
  148. #endif
  149. {
  150. /* Get pointers to the IPv6 header and the offset UDP header */
  151. FAR struct ipv6_hdr_s *ipv6 = IPv6BUF;
  152. DEBUGASSERT(IFF_IS_IPv6(dev->d_flags));
  153. udp = UDPIPv6BUF;
  154. /* Initialize the IPv6 header. Note that the IP length field
  155. * does not include the IPv6 IP header length.
  156. */
  157. ipv6->vtc = 0x60;
  158. ipv6->tcf = 0x00;
  159. ipv6->flow = 0x00;
  160. ipv6->proto = IP_PROTO_UDP;
  161. ipv6->ttl = conn->ttl;
  162. net_ipv6addr_copy(ipv6->srcipaddr, dev->d_ipv6addr);
  163. net_ipv6addr_copy(ipv6->destipaddr, conn->u.ipv6.raddr);
  164. /* The IPv6 length, Includes the UDP header size but not the IPv6
  165. * header size
  166. */
  167. dev->d_len = dev->d_sndlen + UDP_HDRLEN;
  168. ipv6->len[0] = (dev->d_len >> 8);
  169. ipv6->len[1] = (dev->d_len & 0xff);
  170. /* The total length to send is the size of the application data
  171. * plus the IPv6 and UDP headers (and, eventually, the link layer
  172. * header)
  173. */
  174. dev->d_len += IPv6_HDRLEN;
  175. #ifdef CONFIG_NET_STATISTICS
  176. g_netstats.ipv6.sent++;
  177. #endif
  178. }
  179. #endif /* CONFIG_NET_IPv6 */
  180. /* Initialize the UDP header */
  181. udp->srcport = conn->lport;
  182. udp->destport = conn->rport;
  183. udp->udplen = HTONS(dev->d_sndlen + UDP_HDRLEN);
  184. udp->udpchksum = 0;
  185. #ifdef CONFIG_NET_UDP_CHECKSUMS
  186. /* Calculate UDP checksum. */
  187. #ifdef CONFIG_NET_IPv4
  188. #ifdef CONFIG_NET_IPv6
  189. if (conn->domain == PF_INET ||
  190. (conn->domain == PF_INET6 &&
  191. ip6_is_ipv4addr((FAR struct in6_addr *)conn->u.ipv6.raddr)))
  192. #endif
  193. {
  194. udp->udpchksum = ~udp_ipv4_chksum(dev);
  195. }
  196. #endif /* CONFIG_NET_IPv4 */
  197. #ifdef CONFIG_NET_IPv6
  198. #ifdef CONFIG_NET_IPv4
  199. else
  200. #endif
  201. {
  202. udp->udpchksum = ~udp_ipv6_chksum(dev);
  203. }
  204. #endif /* CONFIG_NET_IPv6 */
  205. if (udp->udpchksum == 0)
  206. {
  207. udp->udpchksum = 0xffff;
  208. }
  209. #endif /* CONFIG_NET_UDP_CHECKSUMS */
  210. ninfo("Outgoing UDP packet length: %d\n", dev->d_len);
  211. #ifdef CONFIG_NET_STATISTICS
  212. g_netstats.udp.sent++;
  213. #endif
  214. }
  215. }
  216. #endif /* CONFIG_NET && CONFIG_NET_UDP */