igmp_send.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /****************************************************************************
  2. * net/igmp/igmp_send.c
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. /****************************************************************************
  21. * Included Files
  22. ****************************************************************************/
  23. #include <nuttx/config.h>
  24. #include <debug.h>
  25. #include <arpa/inet.h>
  26. #include <nuttx/net/netconfig.h>
  27. #include <nuttx/net/netdev.h>
  28. #include <nuttx/net/netstats.h>
  29. #include <nuttx/net/ip.h>
  30. #include <nuttx/net/ipopt.h>
  31. #include <nuttx/net/tcp.h>
  32. #include <nuttx/net/igmp.h>
  33. #include "devif/devif.h"
  34. #include "inet/inet.h"
  35. #include "igmp/igmp.h"
  36. #ifdef CONFIG_NET_IGMP
  37. /****************************************************************************
  38. * Pre-processor Definitions
  39. ****************************************************************************/
  40. /* Debug */
  41. #undef IGMP_DUMPPKT /* Define to enable packet dump */
  42. #ifndef CONFIG_DEBUG_NET
  43. # undef IGMP_DUMPPKT
  44. #endif
  45. #ifdef IGMP_DUMPPKT
  46. # define igmp_dumppkt(b,n) lib_dumpbuffer("IGMP", (FAR const uint8_t*)(b), (n))
  47. #else
  48. # define igmp_dumppkt(b,n)
  49. #endif
  50. /* Buffer layout */
  51. #define RASIZE (4)
  52. #define IPv4BUF ((FAR struct igmp_iphdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
  53. #define IGMPBUF(hl) ((FAR struct igmp_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev) + (hl)])
  54. /****************************************************************************
  55. * Private Functions
  56. ****************************************************************************/
  57. static uint16_t igmp_chksum(FAR uint8_t *buffer, int buflen)
  58. {
  59. uint16_t sum = net_chksum((FAR uint16_t *)buffer, buflen);
  60. return sum ? sum : 0xffff;
  61. }
  62. /****************************************************************************
  63. * Public Functions
  64. ****************************************************************************/
  65. /****************************************************************************
  66. * Name: igmp_send
  67. *
  68. * Description:
  69. * Sends an IGMP IP packet on a network interface. This function constructs
  70. * the IP header and calculates the IP header checksum.
  71. *
  72. * Input Parameters:
  73. * dev - The device driver structure to use in the send operation.
  74. * group - Describes the multicast group member and identifies the
  75. * message to be sent.
  76. * destipaddr - The IP address of the recipient of the message
  77. * msgid - ID of message to send
  78. *
  79. * Returned Value:
  80. * None
  81. *
  82. * Assumptions:
  83. * The network is locked.
  84. *
  85. ****************************************************************************/
  86. void igmp_send(FAR struct net_driver_s *dev, FAR struct igmp_group_s *group,
  87. FAR in_addr_t *destipaddr, uint8_t msgid)
  88. {
  89. FAR struct igmp_iphdr_s *ipv4 = IPv4BUF;
  90. FAR struct igmp_hdr_s *igmp;
  91. uint16_t iphdrlen;
  92. ninfo("msgid: %02x destipaddr: %08x\n", msgid, (int)*destipaddr);
  93. /* The IGMP header immediately follows the IP header */
  94. iphdrlen = IPv4_HDRLEN + RASIZE;
  95. igmp = IGMPBUF(iphdrlen);
  96. /* The total length to send is the size of the IP and IGMP headers and 4
  97. * bytes for the ROUTER ALERT (and, eventually, the Ethernet header)
  98. */
  99. dev->d_len = iphdrlen + IGMP_HDRLEN;
  100. /* The total size of the data is the size of the IGMP header */
  101. dev->d_sndlen = IGMP_HDRLEN;
  102. /* Add the router alert option to the IPv4 header (RFC 2113) */
  103. ipv4->ra[0] = HTONS(IPOPT_RA >> 16);
  104. ipv4->ra[1] = HTONS(IPOPT_RA & 0xffff);
  105. /* Initialize the IPv4 header */
  106. ipv4->vhl = 0x46; /* 4->IP; 6->24 bytes */
  107. ipv4->tos = 0;
  108. ipv4->len[0] = (dev->d_len >> 8);
  109. ipv4->len[1] = (dev->d_len & 0xff);
  110. ++g_ipid;
  111. ipv4->ipid[0] = g_ipid >> 8;
  112. ipv4->ipid[1] = g_ipid & 0xff;
  113. ipv4->ipoffset[0] = IP_FLAG_DONTFRAG >> 8;
  114. ipv4->ipoffset[1] = IP_FLAG_DONTFRAG & 0xff;
  115. ipv4->ttl = IGMP_TTL;
  116. ipv4->proto = IP_PROTO_IGMP;
  117. net_ipv4addr_hdrcopy(ipv4->srcipaddr, &dev->d_ipaddr);
  118. net_ipv4addr_hdrcopy(ipv4->destipaddr, destipaddr);
  119. /* Calculate IP checksum. */
  120. ipv4->ipchksum = 0;
  121. ipv4->ipchksum = ~igmp_chksum((FAR uint8_t *)igmp, iphdrlen);
  122. /* Set up the IGMP message */
  123. igmp->type = msgid;
  124. igmp->maxresp = 0;
  125. net_ipv4addr_hdrcopy(igmp->grpaddr, &group->grpaddr);
  126. /* Calculate the IGMP checksum. */
  127. igmp->chksum = 0;
  128. igmp->chksum = ~igmp_chksum(&igmp->type, IGMP_HDRLEN);
  129. IGMP_STATINCR(g_netstats.igmp.poll_send);
  130. IGMP_STATINCR(g_netstats.ipv4.sent);
  131. ninfo("Outgoing IGMP packet length: %d (%d)\n",
  132. dev->d_len, (ipv4->len[0] << 8) | ipv4->len[1]);
  133. igmp_dumppkt(RA, iphdrlen + IGMP_HDRLEN);
  134. }
  135. #endif /* CONFIG_NET_IGMP */