123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- /****************************************************************************
- * net/udp/udp_finddev.c
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership. The
- * ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- *
- ****************************************************************************/
- /****************************************************************************
- * Included Files
- ****************************************************************************/
- #include <nuttx/config.h>
- #if defined(CONFIG_NET) && defined(CONFIG_NET_UDP)
- #include <string.h>
- #include <nuttx/net/netdev.h>
- #include <nuttx/net/ip.h>
- #include "netdev/netdev.h"
- #include "inet/inet.h"
- #include "udp/udp.h"
- /****************************************************************************
- * Private Functions
- ****************************************************************************/
- /****************************************************************************
- * Name: upd_bound_device
- *
- * Description:
- * If the UDP socket is bound to a device, return the reference to the
- * bound device.
- *
- * Input Parameters:
- * conn - UDP connection structure (not currently used).
- *
- * Returned Value:
- * A reference to the bound device. If the retained interface index no
- * longer refers to a valid device, this function will unbind the device
- * and return an arbitrary network device at the head of the list of
- * registered devices. This supports legacy IPv4 DHCPD behavior when
- * there is only a single registered network device.
- *
- ****************************************************************************/
- #ifdef CONFIG_NET_UDP_BINDTODEVICE
- static FAR struct net_driver_s *upd_bound_device(FAR struct udp_conn_s *conn)
- {
- FAR struct net_driver_s *dev = NULL;
- /* Is the UDP socket bound to a device? */
- if (conn->boundto != 0)
- {
- /* Yes..This socket has been bound to an interface. Convert the
- * interface index into a device structure reference.
- */
- dev = netdev_findbyindex(conn->boundto);
- if (dev == NULL)
- {
- /* No device? It must have been unregistered. Un-bind the UDP
- * socket.
- */
- conn->boundto = 0;
- }
- }
- /* If no device was bound or the bound device is no longer valid,
- * then let's try the default network device.
- */
- return dev == NULL ? netdev_default() : dev;
- }
- #else
- # define upd_bound_device(c) netdev_default();
- #endif
- /****************************************************************************
- * Public Functions
- ****************************************************************************/
- /****************************************************************************
- * Name: udp_find_laddr_device
- *
- * Description:
- * Select the network driver to use with the UDP transaction using the
- * locally bound IP address.
- *
- * This is currently used in the UDP network poll setup to determine
- * which device is being polled.
- *
- * Input Parameters:
- * conn - UDP connection structure (not currently used).
- *
- * Returned Value:
- * A pointer to the network driver to use. NULL is returned if driver is
- * not bound to any local device.
- *
- ****************************************************************************/
- FAR struct net_driver_s *udp_find_laddr_device(FAR struct udp_conn_s *conn)
- {
- /* There are multiple network devices. We need to select the device that
- * is going to route the UDP packet based on the provided IP address.
- */
- #ifdef CONFIG_NET_IPv4
- #ifdef CONFIG_NET_IPv6
- if (conn->domain == PF_INET)
- #endif
- {
- /* Make sure that the socket is bound to some non-zero, local
- * address. Zero is used as an indication that the laddr is
- * uninitialized and that the socket is, hence, not bound.
- */
- if (conn->u.ipv4.laddr == 0)
- {
- return NULL;
- }
- else
- {
- return netdev_findby_ripv4addr(conn->u.ipv4.laddr,
- conn->u.ipv4.laddr);
- }
- }
- #endif
- #ifdef CONFIG_NET_IPv6
- #ifdef CONFIG_NET_IPv4
- else
- #endif
- {
- /* Make sure that the socket is bound to some non-zero, local
- * address. The IPv6 unspecified address is used as an indication
- * that the laddr is uninitialized and that the socket is, hence,
- * not bound.
- */
- if (net_ipv6addr_cmp(conn->u.ipv6.laddr, g_ipv6_unspecaddr))
- {
- return NULL;
- }
- else
- {
- return netdev_findby_ripv6addr(conn->u.ipv6.laddr,
- conn->u.ipv6.laddr);
- }
- }
- #endif
- }
- /****************************************************************************
- * Name: udp_find_raddr_device
- *
- * Description:
- * Select the network driver to use with the UDP transaction using the
- * remote IP address.
- *
- * This function is called for UDP sendto() in order to determine which
- * network device that the UDP pack should be sent on.
- *
- * Input Parameters:
- * conn - UDP connection structure.
- *
- * Returned Value:
- * A pointer to the network driver to use.
- *
- ****************************************************************************/
- FAR struct net_driver_s *udp_find_raddr_device(FAR struct udp_conn_s *conn)
- {
- /* We need to select the device that is going to route the UDP packet
- * based on the provided IP address.
- */
- #ifdef CONFIG_NET_IPv4
- #ifdef CONFIG_NET_IPv6
- if (conn->domain == PF_INET)
- #endif
- {
- /* Check if the remote, destination address is the broadcast
- * or multicast address. If this is the case, select the device
- * using the locally bound address (assuming that there is one).
- */
- if (conn->u.ipv4.raddr == INADDR_BROADCAST ||
- IN_MULTICAST(NTOHL(conn->u.ipv4.raddr)))
- {
- /* Make sure that the socket is bound to some non-zero, local
- * address. Zero is used as an indication that the laddr is
- * uninitialized and that the socket is, hence, not bound.
- */
- if (conn->u.ipv4.laddr == 0) /* INADDR_ANY */
- {
- /* Return the device bound to this UDP socket, if any */
- return upd_bound_device(conn);
- }
- else
- {
- return netdev_findby_ripv4addr(conn->u.ipv4.laddr,
- conn->u.ipv4.laddr);
- }
- }
- /* There is no unique device associated with the unspecified
- * address.
- */
- else if (conn->u.ipv4.raddr != INADDR_ANY)
- {
- /* Normal lookup using the verified remote address */
- return netdev_findby_ripv4addr(conn->u.ipv4.laddr,
- conn->u.ipv4.raddr);
- }
- else
- {
- /* Not a suitable IPv4 unicast address for device lookup.
- * Return the device bound to this UDP socket, if any.
- */
- return upd_bound_device(conn);
- }
- }
- #endif
- #ifdef CONFIG_NET_IPv6
- #ifdef CONFIG_NET_IPv4
- else
- #endif
- {
- /* Check if the remote, destination address is a multicast
- * address. If this is the case, select the device
- * using the locally bound address (assuming that there is one).
- */
- if (net_is_addr_mcast(conn->u.ipv6.raddr))
- {
- /* Make sure that the socket is bound to some non-zero, local
- * address. The IPv6 unspecified address is used as an
- * indication that the laddr is uninitialized and that the
- * socket is, hence, not bound.
- */
- if (net_ipv6addr_cmp(conn->u.ipv6.laddr, g_ipv6_unspecaddr))
- {
- /* Return the device bound to this UDP socket, if any */
- return upd_bound_device(conn);
- }
- else
- {
- return netdev_findby_ripv6addr(conn->u.ipv6.laddr,
- conn->u.ipv6.laddr);
- }
- }
- /* There is no unique device associated with the unspecified
- * address.
- */
- else if (!net_ipv6addr_cmp(conn->u.ipv6.raddr, g_ipv6_unspecaddr))
- {
- /* Normal lookup using the verified remote address */
- return netdev_findby_ripv6addr(conn->u.ipv6.laddr,
- conn->u.ipv6.raddr);
- }
- else
- {
- /* Not a suitable IPv6 unicast address for device lookup.
- * Return the device bound to this UDP socket, if any.
- */
- return upd_bound_device(conn);
- }
- }
- #endif
- }
- #endif /* CONFIG_NET && CONFIG_NET_UDP */
|