udp_finddev.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /****************************************************************************
  2. * net/udp/udp_finddev.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. #if defined(CONFIG_NET) && defined(CONFIG_NET_UDP)
  25. #include <string.h>
  26. #include <nuttx/net/netdev.h>
  27. #include <nuttx/net/ip.h>
  28. #include "netdev/netdev.h"
  29. #include "inet/inet.h"
  30. #include "udp/udp.h"
  31. /****************************************************************************
  32. * Private Functions
  33. ****************************************************************************/
  34. /****************************************************************************
  35. * Name: upd_bound_device
  36. *
  37. * Description:
  38. * If the UDP socket is bound to a device, return the reference to the
  39. * bound device.
  40. *
  41. * Input Parameters:
  42. * conn - UDP connection structure (not currently used).
  43. *
  44. * Returned Value:
  45. * A reference to the bound device. If the retained interface index no
  46. * longer refers to a valid device, this function will unbind the device
  47. * and return an arbitrary network device at the head of the list of
  48. * registered devices. This supports legacy IPv4 DHCPD behavior when
  49. * there is only a single registered network device.
  50. *
  51. ****************************************************************************/
  52. #ifdef CONFIG_NET_UDP_BINDTODEVICE
  53. static FAR struct net_driver_s *upd_bound_device(FAR struct udp_conn_s *conn)
  54. {
  55. FAR struct net_driver_s *dev = NULL;
  56. /* Is the UDP socket bound to a device? */
  57. if (conn->boundto != 0)
  58. {
  59. /* Yes..This socket has been bound to an interface. Convert the
  60. * interface index into a device structure reference.
  61. */
  62. dev = netdev_findbyindex(conn->boundto);
  63. if (dev == NULL)
  64. {
  65. /* No device? It must have been unregistered. Un-bind the UDP
  66. * socket.
  67. */
  68. conn->boundto = 0;
  69. }
  70. }
  71. /* If no device was bound or the bound device is no longer valid,
  72. * then let's try the default network device.
  73. */
  74. return dev == NULL ? netdev_default() : dev;
  75. }
  76. #else
  77. # define upd_bound_device(c) netdev_default();
  78. #endif
  79. /****************************************************************************
  80. * Public Functions
  81. ****************************************************************************/
  82. /****************************************************************************
  83. * Name: udp_find_laddr_device
  84. *
  85. * Description:
  86. * Select the network driver to use with the UDP transaction using the
  87. * locally bound IP address.
  88. *
  89. * This is currently used in the UDP network poll setup to determine
  90. * which device is being polled.
  91. *
  92. * Input Parameters:
  93. * conn - UDP connection structure (not currently used).
  94. *
  95. * Returned Value:
  96. * A pointer to the network driver to use. NULL is returned if driver is
  97. * not bound to any local device.
  98. *
  99. ****************************************************************************/
  100. FAR struct net_driver_s *udp_find_laddr_device(FAR struct udp_conn_s *conn)
  101. {
  102. /* There are multiple network devices. We need to select the device that
  103. * is going to route the UDP packet based on the provided IP address.
  104. */
  105. #ifdef CONFIG_NET_IPv4
  106. #ifdef CONFIG_NET_IPv6
  107. if (conn->domain == PF_INET)
  108. #endif
  109. {
  110. /* Make sure that the socket is bound to some non-zero, local
  111. * address. Zero is used as an indication that the laddr is
  112. * uninitialized and that the socket is, hence, not bound.
  113. */
  114. if (conn->u.ipv4.laddr == 0)
  115. {
  116. return NULL;
  117. }
  118. else
  119. {
  120. return netdev_findby_ripv4addr(conn->u.ipv4.laddr,
  121. conn->u.ipv4.laddr);
  122. }
  123. }
  124. #endif
  125. #ifdef CONFIG_NET_IPv6
  126. #ifdef CONFIG_NET_IPv4
  127. else
  128. #endif
  129. {
  130. /* Make sure that the socket is bound to some non-zero, local
  131. * address. The IPv6 unspecified address is used as an indication
  132. * that the laddr is uninitialized and that the socket is, hence,
  133. * not bound.
  134. */
  135. if (net_ipv6addr_cmp(conn->u.ipv6.laddr, g_ipv6_unspecaddr))
  136. {
  137. return NULL;
  138. }
  139. else
  140. {
  141. return netdev_findby_ripv6addr(conn->u.ipv6.laddr,
  142. conn->u.ipv6.laddr);
  143. }
  144. }
  145. #endif
  146. }
  147. /****************************************************************************
  148. * Name: udp_find_raddr_device
  149. *
  150. * Description:
  151. * Select the network driver to use with the UDP transaction using the
  152. * remote IP address.
  153. *
  154. * This function is called for UDP sendto() in order to determine which
  155. * network device that the UDP pack should be sent on.
  156. *
  157. * Input Parameters:
  158. * conn - UDP connection structure.
  159. *
  160. * Returned Value:
  161. * A pointer to the network driver to use.
  162. *
  163. ****************************************************************************/
  164. FAR struct net_driver_s *udp_find_raddr_device(FAR struct udp_conn_s *conn)
  165. {
  166. /* We need to select the device that is going to route the UDP packet
  167. * based on the provided IP address.
  168. */
  169. #ifdef CONFIG_NET_IPv4
  170. #ifdef CONFIG_NET_IPv6
  171. if (conn->domain == PF_INET)
  172. #endif
  173. {
  174. /* Check if the remote, destination address is the broadcast
  175. * or multicast address. If this is the case, select the device
  176. * using the locally bound address (assuming that there is one).
  177. */
  178. if (conn->u.ipv4.raddr == INADDR_BROADCAST ||
  179. IN_MULTICAST(NTOHL(conn->u.ipv4.raddr)))
  180. {
  181. /* Make sure that the socket is bound to some non-zero, local
  182. * address. Zero is used as an indication that the laddr is
  183. * uninitialized and that the socket is, hence, not bound.
  184. */
  185. if (conn->u.ipv4.laddr == 0) /* INADDR_ANY */
  186. {
  187. /* Return the device bound to this UDP socket, if any */
  188. return upd_bound_device(conn);
  189. }
  190. else
  191. {
  192. return netdev_findby_ripv4addr(conn->u.ipv4.laddr,
  193. conn->u.ipv4.laddr);
  194. }
  195. }
  196. /* There is no unique device associated with the unspecified
  197. * address.
  198. */
  199. else if (conn->u.ipv4.raddr != INADDR_ANY)
  200. {
  201. /* Normal lookup using the verified remote address */
  202. return netdev_findby_ripv4addr(conn->u.ipv4.laddr,
  203. conn->u.ipv4.raddr);
  204. }
  205. else
  206. {
  207. /* Not a suitable IPv4 unicast address for device lookup.
  208. * Return the device bound to this UDP socket, if any.
  209. */
  210. return upd_bound_device(conn);
  211. }
  212. }
  213. #endif
  214. #ifdef CONFIG_NET_IPv6
  215. #ifdef CONFIG_NET_IPv4
  216. else
  217. #endif
  218. {
  219. /* Check if the remote, destination address is a multicast
  220. * address. If this is the case, select the device
  221. * using the locally bound address (assuming that there is one).
  222. */
  223. if (net_is_addr_mcast(conn->u.ipv6.raddr))
  224. {
  225. /* Make sure that the socket is bound to some non-zero, local
  226. * address. The IPv6 unspecified address is used as an
  227. * indication that the laddr is uninitialized and that the
  228. * socket is, hence, not bound.
  229. */
  230. if (net_ipv6addr_cmp(conn->u.ipv6.laddr, g_ipv6_unspecaddr))
  231. {
  232. /* Return the device bound to this UDP socket, if any */
  233. return upd_bound_device(conn);
  234. }
  235. else
  236. {
  237. return netdev_findby_ripv6addr(conn->u.ipv6.laddr,
  238. conn->u.ipv6.laddr);
  239. }
  240. }
  241. /* There is no unique device associated with the unspecified
  242. * address.
  243. */
  244. else if (!net_ipv6addr_cmp(conn->u.ipv6.raddr, g_ipv6_unspecaddr))
  245. {
  246. /* Normal lookup using the verified remote address */
  247. return netdev_findby_ripv6addr(conn->u.ipv6.laddr,
  248. conn->u.ipv6.raddr);
  249. }
  250. else
  251. {
  252. /* Not a suitable IPv6 unicast address for device lookup.
  253. * Return the device bound to this UDP socket, if any.
  254. */
  255. return upd_bound_device(conn);
  256. }
  257. }
  258. #endif
  259. }
  260. #endif /* CONFIG_NET && CONFIG_NET_UDP */