net/sockopt: move BINDTODEVICE to socket level
rename the UDP_BINDTODEVICE to SO_BINDTODEVICE to follow the linux style to be compatible with non-UDP protocol binding requirements Signed-off-by: chao.an <anchao@xiaomi.com>
This commit is contained in:
parent
50177dbae1
commit
9cb17841d8
@ -143,6 +143,7 @@
|
||||
#define NUTTX_SO_SNDTIMEO 14
|
||||
#define NUTTX_SO_TYPE 15
|
||||
#define NUTTX_SO_TIMESTAMP 16
|
||||
#define NUTTX_SO_BINDTODEVICE 17
|
||||
|
||||
#define NUTTX_SO_SNDBUFFORCE 32
|
||||
#define NUTTX_SO_RCVBUFFORCE 33
|
||||
|
@ -56,6 +56,7 @@ CONFIG_NETUTILS_TELNETC=y
|
||||
CONFIG_NETUTILS_TELNETD=y
|
||||
CONFIG_NET_ARP_IPIN=y
|
||||
CONFIG_NET_ARP_SEND=y
|
||||
CONFIG_NET_BINDTODEVICE=y
|
||||
CONFIG_NET_BROADCAST=y
|
||||
CONFIG_NET_ETH_PKTSIZE=1514
|
||||
CONFIG_NET_GUARDSIZE=4
|
||||
@ -71,7 +72,6 @@ CONFIG_NET_TCPBACKLOG=y
|
||||
CONFIG_NET_TCP_NPOLLWAITERS=4
|
||||
CONFIG_NET_TCP_WRITE_BUFFERS=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_UDP_BINDTODEVICE=y
|
||||
CONFIG_NET_UDP_CHECKSUMS=y
|
||||
CONFIG_NET_UDP_NPOLLWAITERS=8
|
||||
CONFIG_NET_UDP_WRITE_BUFFERS=y
|
||||
|
@ -50,7 +50,6 @@
|
||||
#define IFF_UP (1 << 1) /* Interface is up */
|
||||
#define IFF_RUNNING (1 << 2) /* Carrier is available */
|
||||
#define IFF_IPv6 (1 << 3) /* Configured for IPv6 packet (vs ARP or IPv4) */
|
||||
#define IFF_BOUND (1 << 4) /* Bound to a socket */
|
||||
#define IFF_LOOPBACK (1 << 5) /* Is a loopback net */
|
||||
#define IFF_POINTOPOINT (1 << 6) /* Is point-to-point link */
|
||||
#define IFF_NOARP (1 << 7) /* ARP is not required for this packet */
|
||||
@ -61,7 +60,6 @@
|
||||
|
||||
#define IFF_SET_UP(f) do { (f) |= IFF_UP; } while (0)
|
||||
#define IFF_SET_RUNNING(f) do { (f) |= IFF_RUNNING; } while (0)
|
||||
#define IFF_SET_BOUND(f) do { (f) |= IFF_BOUND; } while (0)
|
||||
#define IFF_SET_NOARP(f) do { (f) |= IFF_NOARP; } while (0)
|
||||
#define IFF_SET_LOOPBACK(f) do { (f) |= IFF_LOOPBACK; } while (0)
|
||||
#define IFF_SET_POINTOPOINT(f) do { (f) |= IFF_POINTOPOINT; } while (0)
|
||||
@ -70,7 +68,6 @@
|
||||
|
||||
#define IFF_CLR_UP(f) do { (f) &= ~IFF_UP; } while (0)
|
||||
#define IFF_CLR_RUNNING(f) do { (f) &= ~IFF_RUNNING; } while (0)
|
||||
#define IFF_CLR_BOUND(f) do { (f) &= ~IFF_BOUND; } while (0)
|
||||
#define IFF_CLR_NOARP(f) do { (f) &= ~IFF_NOARP; } while (0)
|
||||
#define IFF_CLR_LOOPBACK(f) do { (f) &= ~IFF_LOOPBACK; } while (0)
|
||||
#define IFF_CLR_POINTOPOINT(f) do { (f) &= ~IFF_POINTOPOINT; } while (0)
|
||||
@ -79,7 +76,6 @@
|
||||
|
||||
#define IFF_IS_UP(f) (((f) & IFF_UP) != 0)
|
||||
#define IFF_IS_RUNNING(f) (((f) & IFF_RUNNING) != 0)
|
||||
#define IFF_IS_BOUND(f) (((f) & IFF_BOUND) != 0)
|
||||
#define IFF_IS_NOARP(f) (((f) & IFF_NOARP) != 0)
|
||||
#define IFF_IS_LOOPBACK(f) (((f) & IFF_LOOPBACK) != 0)
|
||||
#define IFF_IS_POINTOPOINT(f) (((f) & IFF_POINTOPOINT) != 0)
|
||||
|
@ -31,10 +31,4 @@
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* UDP protocol (SOL_UDP) socket options */
|
||||
|
||||
#define UDP_BINDTODEVICE (__SO_PROTOCOL + 0) /* Bind this UDP socket to a
|
||||
* specific network device.
|
||||
*/
|
||||
|
||||
#endif /* __INCLUDE_NETINET_UDP_H */
|
||||
|
@ -246,6 +246,10 @@ struct socket_conn_s
|
||||
#ifdef CONFIG_NET_TIMESTAMP
|
||||
int32_t s_timestamp; /* Socket timestamp enabled/disabled */
|
||||
#endif
|
||||
#ifdef CONFIG_NET_BINDTODEVICE
|
||||
uint8_t s_boundto; /* Index of the interface we are bound to.
|
||||
* Unbound: 0, Bound: 1-MAX_IFINDEX */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Connection-specific content may follow */
|
||||
|
@ -200,6 +200,8 @@
|
||||
#define SO_TIMESTAMP 16 /* Generates a timestamp for each incoming packet
|
||||
* arg: integer value
|
||||
*/
|
||||
#define SO_BINDTODEVICE 17 /* Bind this socket to a specific network device.
|
||||
*/
|
||||
|
||||
/* The options are unsupported but included for compatibility
|
||||
* and portability
|
||||
|
@ -297,13 +297,13 @@ int ipv4_input(FAR struct net_driver_s *dev)
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if defined(NET_UDP_HAVE_STACK) && defined(CONFIG_NET_UDP_BINDTODEVICE)
|
||||
/* If the UDP protocol specific socket option UDP_BINDTODEVICE
|
||||
#if defined(NET_UDP_HAVE_STACK) && defined(CONFIG_NET_BINDTODEVICE)
|
||||
/* If the protocol specific socket option NET_BINDTODEVICE
|
||||
* is selected, then we must forward all UDP packets to the bound
|
||||
* socket.
|
||||
*/
|
||||
|
||||
if (ipv4->proto != IP_PROTO_UDP || !IFF_IS_BOUND(dev->d_flags))
|
||||
if (ipv4->proto != IP_PROTO_UDP)
|
||||
#endif
|
||||
{
|
||||
/* Not destined for us and not forwardable... Drop the
|
||||
|
@ -379,13 +379,13 @@ int ipv6_input(FAR struct net_driver_s *dev)
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if defined(NET_UDP_HAVE_STACK) && defined(CONFIG_NET_UDP_BINDTODEVICE)
|
||||
/* If the UDP protocol specific socket option UDP_BINDTODEVICE
|
||||
#if defined(NET_UDP_HAVE_STACK) && defined(CONFIG_NET_BINDTODEVICE)
|
||||
/* If the protocol specific socket option NET_BINDTODEVICE
|
||||
* is selected, then we must forward all UDP packets to the bound
|
||||
* socket.
|
||||
*/
|
||||
|
||||
if (nxthdr != IP_PROTO_UDP || !IFF_IS_BOUND(dev->d_flags))
|
||||
if (nxthdr != IP_PROTO_UDP)
|
||||
#endif
|
||||
{
|
||||
/* Not destined for us and not forwardable...
|
||||
|
@ -56,6 +56,15 @@ config NET_TIMESTAMP
|
||||
---help---
|
||||
Enable or disable support for the SO_TIMESTAMP socket option. Currently only tested & implemented in SocketCAN but should work on all sockets
|
||||
|
||||
config NET_BINDTODEVICE
|
||||
bool "SO_BINDTODEVICE socket option Bind-to-device support"
|
||||
default n
|
||||
select NETDEV_IFINDEX
|
||||
---help---
|
||||
Enable support for the NET_BINDTODEVICE socket option.
|
||||
Linux has SO_BINDTODEVICE but in NuttX this option is instead
|
||||
specific to the UDP protocol.
|
||||
|
||||
endif # NET_SOCKOPTS
|
||||
|
||||
endmenu # Socket Support
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <arch/irq.h>
|
||||
|
||||
#include <nuttx/net/net.h>
|
||||
#include <netdev/netdev.h>
|
||||
|
||||
#include "socket/socket.h"
|
||||
#include "inet/inet.h"
|
||||
@ -399,6 +400,51 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_BINDTODEVICE
|
||||
/* Handle the SO_BINDTODEVICE socket-level option.
|
||||
*
|
||||
* NOTE: this option 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 SO_BINDTODEVICE: /* Bind socket to a specific network device */
|
||||
{
|
||||
FAR struct net_driver_s *dev;
|
||||
|
||||
/* Check if we are are unbinding the socket */
|
||||
|
||||
if (value == NULL || value_len == 0 ||
|
||||
(value_len > 0 && ((FAR char *)value)[0] == 0))
|
||||
{
|
||||
conn->s_boundto = 0; /* This interface is no longer bound */
|
||||
break;
|
||||
}
|
||||
|
||||
/* No, we are binding a socket to the interface
|
||||
* Find the interface device with this name.
|
||||
*/
|
||||
|
||||
dev = netdev_findbyname(value);
|
||||
if (dev == NULL)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Bind the socket to the interface */
|
||||
|
||||
DEBUGASSERT(dev->d_ifindex > 0 &&
|
||||
dev->d_ifindex <= MAX_IFINDEX);
|
||||
conn->s_boundto = dev->d_ifindex;
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The following are not yet implemented */
|
||||
|
||||
case SO_RCVLOWAT: /* Sets the minimum number of bytes to input */
|
||||
|
@ -61,10 +61,12 @@
|
||||
#define _SO_SNDLOWAT _SO_BIT(SO_SNDLOWAT)
|
||||
#define _SO_SNDTIMEO _SO_BIT(SO_SNDTIMEO)
|
||||
#define _SO_TYPE _SO_BIT(SO_TYPE)
|
||||
#define _SO_TIMESTAMP _SO_BIT(SO_TIMESTAMP)
|
||||
#define _SO_BINDTODEVICE _SO_BIT(SO_BINDTODEVICE)
|
||||
|
||||
/* This is the largest option value. REVISIT: belongs in sys/socket.h */
|
||||
|
||||
#define _SO_MAXOPT (16)
|
||||
#define _SO_MAXOPT (18)
|
||||
|
||||
/* Macros to set, test, clear options */
|
||||
|
||||
|
@ -32,16 +32,6 @@ endif # NET_UDP
|
||||
|
||||
if NET_UDP && !NET_UDP_NO_STACK
|
||||
|
||||
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
|
||||
specific to the UDP protocol.
|
||||
|
||||
config NET_UDP_CHECKSUMS
|
||||
bool "UDP checksums"
|
||||
default y if NET_IPv6
|
||||
|
@ -112,10 +112,6 @@ 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
|
||||
#if CONFIG_NET_RECV_BUFSIZE > 0
|
||||
int32_t rcvbufs; /* Maximum amount of bytes queued in recv */
|
||||
#endif
|
||||
|
@ -29,14 +29,10 @@
|
||||
#include <debug.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <nuttx/net/net.h>
|
||||
#include <nuttx/net/netdev.h>
|
||||
#include <nuttx/net/udp.h>
|
||||
|
||||
#include "devif/devif.h"
|
||||
#include "netdev/netdev.h"
|
||||
#include "udp/udp.h"
|
||||
#include "socket/socket.h"
|
||||
|
||||
@ -106,28 +102,6 @@ int udp_close(FAR struct socket *psock)
|
||||
nerr("ERROR: udp_txdrain() failed: %d\n", ret);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_UDP_BINDTODEVICE
|
||||
/* Is the socket bound to an interface device */
|
||||
|
||||
if (conn->boundto != 0)
|
||||
{
|
||||
FAR struct net_driver_s *dev;
|
||||
|
||||
/* Yes, get the interface that we are bound do. NULL would indicate
|
||||
* that the interface no longer exists for some reason.
|
||||
*/
|
||||
|
||||
dev = netdev_findbyindex(conn->boundto);
|
||||
if (dev != NULL)
|
||||
{
|
||||
/* Clear the interface flag to unbind the device from the socket.
|
||||
*/
|
||||
|
||||
IFF_CLR_BOUND(dev->d_flags);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
|
||||
/* Free any semi-permanent write buffer callback in place. */
|
||||
|
||||
|
@ -619,9 +619,6 @@ FAR struct udp_conn_s *udp_alloc(uint8_t domain)
|
||||
conn->flags = 0;
|
||||
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
|
||||
conn->domain = domain;
|
||||
#endif
|
||||
#ifdef CONFIG_NET_UDP_BINDTODEVICE
|
||||
conn->boundto = 0; /* Not bound to any interface */
|
||||
#endif
|
||||
conn->lport = 0;
|
||||
conn->ttl = IP_TTL_DEFAULT;
|
||||
|
@ -57,27 +57,27 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_UDP_BINDTODEVICE
|
||||
#ifdef CONFIG_NET_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)
|
||||
if (conn->sconn.s_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);
|
||||
dev = netdev_findbyindex(conn->sconn.s_boundto);
|
||||
if (dev == NULL)
|
||||
{
|
||||
/* No device? It must have been unregistered. Un-bind the UDP
|
||||
* socket.
|
||||
*/
|
||||
|
||||
conn->boundto = 0;
|
||||
conn->sconn.s_boundto = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,127 +74,7 @@
|
||||
int udp_setsockopt(FAR struct socket *psock, int option,
|
||||
FAR const void *value, socklen_t value_len)
|
||||
{
|
||||
#ifdef CONFIG_NET_UDP_BINDTODEVICE
|
||||
/* Keep alive options are the only UDP protocol socket option currently
|
||||
* supported.
|
||||
*/
|
||||
|
||||
FAR struct udp_conn_s *conn;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(psock != NULL && value != NULL && psock->s_conn != NULL);
|
||||
conn = (FAR struct udp_conn_s *)psock->s_conn;
|
||||
|
||||
/* All of the UDP protocol options apply only UDP sockets. The sockets
|
||||
* do not have to be connected.. that might occur later with the KeepAlive
|
||||
* already configured.
|
||||
*/
|
||||
|
||||
if (psock->s_type != SOCK_DGRAM)
|
||||
{
|
||||
nerr("ERROR: Not a UDP socket\n");
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
/* Handle the UDP-protocol options */
|
||||
|
||||
switch (option)
|
||||
{
|
||||
#ifdef CONFIG_NET_UDP_BINDTODEVICE
|
||||
/* Handle the UDP_BINDTODEVICE socket-level option.
|
||||
*
|
||||
* 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 */
|
||||
{
|
||||
FAR struct net_driver_s *dev;
|
||||
|
||||
/* Check if we are are unbinding the socket */
|
||||
|
||||
if (value == NULL || value_len == 0 ||
|
||||
(value_len > 0 && ((FAR char *)value)[0] == 0))
|
||||
{
|
||||
/* Just report success if the socket is not bound to an
|
||||
* interface.
|
||||
*/
|
||||
|
||||
if (conn->boundto != 0)
|
||||
{
|
||||
/* Get the interface that we are bound do. NULL would
|
||||
* indicate that the interface no longer exists for some
|
||||
* reason.
|
||||
*/
|
||||
|
||||
dev = netdev_findbyindex(conn->boundto);
|
||||
if (dev != NULL)
|
||||
{
|
||||
/* Clear the interface flag to unbind the device from
|
||||
* the socket.
|
||||
*/
|
||||
|
||||
IFF_CLR_BOUND(dev->d_flags);
|
||||
}
|
||||
|
||||
conn->boundto = 0; /* This interface is no longer bound */
|
||||
}
|
||||
|
||||
ret = OK;
|
||||
}
|
||||
|
||||
/* No, we are binding a socket to the interface. */
|
||||
|
||||
else
|
||||
{
|
||||
/* Find the interface device with this name */
|
||||
|
||||
dev = netdev_findbyname(value);
|
||||
if (dev == NULL)
|
||||
{
|
||||
ret = -ENODEV;
|
||||
}
|
||||
|
||||
/* An interface may be bound only to one socket. */
|
||||
|
||||
else if (IFF_IS_BOUND(dev->d_flags))
|
||||
{
|
||||
ret = -EBUSY;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Bind the interface to a socket */
|
||||
|
||||
IFF_SET_BOUND(dev->d_flags);
|
||||
|
||||
/* Bind the socket to the interface */
|
||||
|
||||
DEBUGASSERT(dev->d_ifindex > 0 &&
|
||||
dev->d_ifindex <= MAX_IFINDEX);
|
||||
conn->boundto = dev->d_ifindex;
|
||||
ret = OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
nerr("ERROR: Unrecognized UDP option: %d\n", option);
|
||||
ret = -ENOPROTOOPT;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return -ENOPROTOOPT;
|
||||
#endif /* CONFIG_NET_UDP_BINDTODEVICE */
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_UDPPROTO_OPTIONS */
|
||||
|
Loading…
Reference in New Issue
Block a user