net/udp: Finish support for the UDP_BINDTODEVICE protocol socket option
This commit is contained in:
parent
2a29fe0223
commit
65be13bffe
@ -46,6 +46,8 @@
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* UDP protocol (SOL_UDP) socket options */
|
||||
|
||||
#define UDP_BINDTODEVICE (__SO_PROTOCOL + 0) /* Bind this UDP socket to a
|
||||
* specific network device.
|
||||
*/
|
||||
|
@ -30,6 +30,12 @@ config NET_TCPPROTO_OPTIONS
|
||||
---help---
|
||||
Enable or disable support for TCP protocol level socket options.
|
||||
|
||||
config NET_UDPPROTO_OPTIONS
|
||||
bool
|
||||
default n
|
||||
---help---
|
||||
Enable or disable support for UDP protocol level socket options.
|
||||
|
||||
if NET_SOCKOPTS
|
||||
|
||||
config NET_SOLINGER
|
||||
|
@ -25,6 +25,7 @@ config NET_UDP_BINDTODEVICE
|
||||
bool "UDP Bind-to-device support"
|
||||
default n
|
||||
select NET_UDPPROTO_OPTIONS
|
||||
select NETDEV_IFINDEX
|
||||
---help---
|
||||
Enable support for the UDP_BINDTODEVICE socket option.
|
||||
Linux has SO_BINDTODEVICE but in NuttX this option is instead
|
||||
|
@ -112,6 +112,11 @@ struct udp_conn_s
|
||||
uint8_t ttl; /* Default time-to-live */
|
||||
uint8_t crefs; /* Reference counts on this instance */
|
||||
|
||||
#ifdef CONFIG_NET_UDP_BINDTODEVICE
|
||||
uint8_t boundto; /* Index of the interface we are bound to.
|
||||
* Unbound: 0, Bound: 1-MAX_IFINDEX */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_UDP_READAHEAD
|
||||
/* Read-ahead buffering.
|
||||
*
|
||||
|
@ -579,12 +579,15 @@ FAR struct udp_conn_s *udp_alloc(uint8_t domain)
|
||||
{
|
||||
/* Make sure that the connection is marked as uninitialized */
|
||||
|
||||
conn->flags = 0;
|
||||
conn->flags = 0;
|
||||
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
|
||||
conn->domain = domain;
|
||||
conn->domain = domain;
|
||||
#endif
|
||||
conn->lport = 0;
|
||||
conn->ttl = IP_TTL;
|
||||
#ifdef CONFIG_NET_UDP_BINDTODEVICE
|
||||
conn->boundto = 0; /* Not bound to any interface */
|
||||
#endif
|
||||
conn->lport = 0;
|
||||
conn->ttl = IP_TTL;
|
||||
|
||||
#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
|
||||
/* Initialize the write buffer lists */
|
||||
|
@ -167,7 +167,17 @@ FAR struct net_driver_s *udp_find_raddr_device(FAR struct udp_conn_s *conn)
|
||||
|
||||
if (conn->u.ipv4.laddr == 0) /* INADDR_ANY */
|
||||
{
|
||||
return NULL;
|
||||
FAR struct net_driver_s *dev = NULL;
|
||||
|
||||
#ifdef CONFIG_NET_UDP_BINDTODEVICE
|
||||
if (conn->boundto != 0)
|
||||
{
|
||||
/* This socket has been bound to an interface */
|
||||
|
||||
dev = netdev_findbyindex(conn->boundto);
|
||||
}
|
||||
#endif
|
||||
return dev;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -189,9 +199,19 @@ FAR struct net_driver_s *udp_find_raddr_device(FAR struct udp_conn_s *conn)
|
||||
}
|
||||
else
|
||||
{
|
||||
FAR struct net_driver_s *dev = NULL;
|
||||
|
||||
/* Not a suitable IPv4 unicast address for device lookup */
|
||||
|
||||
return NULL;
|
||||
#ifdef CONFIG_NET_UDP_BINDTODEVICE
|
||||
if (conn->boundto != 0)
|
||||
{
|
||||
/* This socket has been bound to an interface */
|
||||
|
||||
dev = netdev_findbyindex(conn->boundto);
|
||||
}
|
||||
#endif
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -216,7 +236,17 @@ FAR struct net_driver_s *udp_find_raddr_device(FAR struct udp_conn_s *conn)
|
||||
|
||||
if (net_ipv6addr_cmp(conn->u.ipv6.laddr, g_ipv6_unspecaddr))
|
||||
{
|
||||
return NULL;
|
||||
FAR struct net_driver_s *dev = NULL;
|
||||
|
||||
#ifdef CONFIG_NET_UDP_BINDTODEVICE
|
||||
if (conn->boundto != 0)
|
||||
{
|
||||
/* This socket has been bound to an interface */
|
||||
|
||||
dev = netdev_findbyindex(conn->boundto);
|
||||
}
|
||||
#endif
|
||||
return dev;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -238,9 +268,19 @@ FAR struct net_driver_s *udp_find_raddr_device(FAR struct udp_conn_s *conn)
|
||||
}
|
||||
else
|
||||
{
|
||||
FAR struct net_driver_s *dev = NULL;
|
||||
|
||||
/* Not a suitable IPv6 unicast address for device lookup */
|
||||
|
||||
return NULL;
|
||||
#ifdef CONFIG_NET_UDP_BINDTODEVICE
|
||||
if (conn->boundto != 0)
|
||||
{
|
||||
/* This socket has been bound to an interface */
|
||||
|
||||
dev = netdev_findbyindex(conn->boundto);
|
||||
}
|
||||
#endif
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -53,6 +53,7 @@
|
||||
|
||||
#include "socket/socket.h"
|
||||
#include "utils/utils.h"
|
||||
#include "netdev/netdev.h"
|
||||
#include "udp/udp.h"
|
||||
|
||||
#ifdef CONFIG_NET_UDPPROTO_OPTIONS
|
||||
@ -104,27 +105,55 @@ int udp_setsockopt(FAR struct socket *psock, int option,
|
||||
* already configured.
|
||||
*/
|
||||
|
||||
if (psock->s_type != SOCK_STREAM)
|
||||
if (psock->s_type != SOCK_DGRAM)
|
||||
{
|
||||
nerr("ERROR: Not a UDP socket\n");
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
/* Handle the Keep-Alive option */
|
||||
/* Handle the UDP-protocol options */
|
||||
|
||||
switch (option)
|
||||
{
|
||||
/* Handle the SO_KEEPALIVE socket-level option.
|
||||
#ifdef CONFIG_NET_UDP_BINDTODEVICE
|
||||
/* Handle the UDP_BINDTODEVICE socket-level option.
|
||||
*
|
||||
* NOTE: SO_KEEPALIVE is not really a socket-level option; it is a
|
||||
* protocol-level option. A given UDP connection may service multiple
|
||||
* sockets (via dup'ing of the socket). There is, however, still only
|
||||
* one connection to be monitored and that is a global attribute across
|
||||
* all of the clones that may use the underlying connection.
|
||||
* NOTE: UDP_BINDTODEVICE is declared in linux as SO_BINDTODEVICE,
|
||||
* but this option only makes sense for UDP sockets trying to broadcast
|
||||
* while their local address is not set, eg, with DHCP requests.
|
||||
* The problem is that we are not able to determine the interface to be
|
||||
* used for sending packets when multiple interfaces do not have a local
|
||||
* address yet. This option can be used to "force" the interface used to
|
||||
* send the UDP traffic in this connection. Note that it does NOT only
|
||||
* apply to broadcast packets.
|
||||
*/
|
||||
|
||||
case UDP_BINDTODEVICE: /* Bind socket to a specific network device */
|
||||
if (value == NULL || value_len == 0 ||
|
||||
(value_len > 0 && ((FAR char *)value)[0] == 0))
|
||||
{
|
||||
conn->boundto = 0; /* This interface is no longer bound */
|
||||
}
|
||||
else
|
||||
{
|
||||
int ifindex;
|
||||
|
||||
/* Get the interface index corresponding to the interface name */
|
||||
|
||||
ifindex = netdev_nametoindex(value);
|
||||
if (ifindex >= 0)
|
||||
{
|
||||
DEBUGASSERT(ifindex > 0 && ifindex < MAX_IFINDEX);
|
||||
conn->boundto = ifindex;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ifindex;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
nerr("ERROR: Unrecognized UDP option: %d\n", option);
|
||||
@ -139,3 +168,4 @@ int udp_setsockopt(FAR struct socket *psock, int option,
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_UDPPROTO_OPTIONS */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user