summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-11-21 14:21:30 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-11-21 14:21:30 -0600
commit938541d0d9c92cf03ab83be43efb1fe35f135fac (patch)
treec18d1479305a038f39946b58f68da9f14e424416
parent632daff495eb718f70a8ea8c311ac6ae683a284d (diff)
downloadnuttx-938541d0d9c92cf03ab83be43efb1fe35f135fac.tar.gz
nuttx-938541d0d9c92cf03ab83be43efb1fe35f135fac.tar.bz2
nuttx-938541d0d9c92cf03ab83be43efb1fe35f135fac.zip
Some ideas for how port assignments might work with multiple network interfaces
-rw-r--r--nuttx/net/udp/udp.h9
-rw-r--r--nuttx/net/udp/udp_conn.c136
2 files changed, 136 insertions, 9 deletions
diff --git a/nuttx/net/udp/udp.h b/nuttx/net/udp/udp.h
index fd46eb310..f13b85517 100644
--- a/nuttx/net/udp/udp.h
+++ b/nuttx/net/udp/udp.h
@@ -66,9 +66,12 @@ struct devif_callback_s; /* Forward reference */
struct udp_conn_s
{
dq_entry_t node; /* Supports a doubly linked list */
- net_ipaddr_t ripaddr; /* The IP address of the remote peer */
- uint16_t lport; /* The local port number in network byte order */
- uint16_t rport; /* The remote port number in network byte order */
+#ifdef CONFIG_NETDEV_MULTINIC
+ net_ipaddr_t lipaddr; /* Bound local IP address (network byte order) */
+#endif
+ net_ipaddr_t ripaddr; /* IP address of remote peer (network byte order) */
+ uint16_t lport; /* Bound local port number (network byte order) */
+ uint16_t rport; /* Remote port number (network byte order) */
uint8_t ttl; /* Default time-to-live */
uint8_t crefs; /* Reference counts on this instance */
diff --git a/nuttx/net/udp/udp_conn.c b/nuttx/net/udp/udp_conn.c
index 3fb4d1ae2..8bdb0a19c 100644
--- a/nuttx/net/udp/udp_conn.c
+++ b/nuttx/net/udp/udp_conn.c
@@ -59,7 +59,9 @@
#include <nuttx/net/udp.h>
#include "devif/devif.h"
+#include "netdev/netdev.h"
#include "udp/udp.h"
+#include "ipv6/ipv6.h"
/****************************************************************************
* Private Data
@@ -119,18 +121,42 @@ static inline void _udp_semtake(FAR sem_t *sem)
*
****************************************************************************/
+#ifdef CONFIG_NETDEV_MULTINIC
+static FAR struct udp_conn_s *udp_find_conn(net_ipaddr_t ipaddr,
+ uint16_t portno)
+#else
static FAR struct udp_conn_s *udp_find_conn(uint16_t portno)
+#endif
{
+ FAR struct udp_conn_s *conn;
int i;
/* Now search each connection structure.*/
for (i = 0; i < CONFIG_NET_UDP_CONNS; i++)
{
- if (g_udp_connections[ i ].lport == portno)
+ conn = &g_udp_connections[i];
+
+#ifdef CONFIG_NETDEV_MULTINIC
+ /* If the port local port number assigned to the connections matches
+ * AND the IP address of the connection matches, then return a
+ * reference to the connection structure.
+ */
+
+ if (conn->lport == portno && net_ipaddr_cmp(conn->lipaddr, ipaddr))
+ {
+ return conn;
+ }
+#else
+ /* If the port local port number assigned to the connections matches,
+ * then return a reference to the connection structure.
+ */
+
+ if (conn->lport == portno)
{
- return &g_udp_connections[i];
+ return conn;
}
+#endif
}
return NULL;
@@ -156,7 +182,11 @@ static FAR struct udp_conn_s *udp_find_conn(uint16_t portno)
*
****************************************************************************/
+#ifdef CONFIG_NETDEV_MULTINIC
+static uint16_t udp_select_port(net_ipaddr_t ipaddr)
+#else
static uint16_t udp_select_port(void)
+#endif
{
uint16_t portno;
@@ -180,7 +210,11 @@ static uint16_t udp_select_port(void)
g_last_udp_port = 4096;
}
}
+#ifdef CONFIG_NETDEV_MULTINIC
+ while (udp_find_conn(ipaddr, htons(g_last_udp_port)));
+#else
while (udp_find_conn(htons(g_last_udp_port)));
+#endif
/* Initialize and return the connection structure, bind it to the
* port number
@@ -379,16 +413,65 @@ int udp_bind(FAR struct udp_conn_s *conn, FAR const struct sockaddr_in6 *addr)
int udp_bind(FAR struct udp_conn_s *conn, FAR const struct sockaddr_in *addr)
#endif
{
- int ret = -EADDRINUSE;
+ FAR struct net_driver_s *dev;
+ net_ipaddr_t ipaddr;
net_lock_t flags;
+ int ret;
+
+#ifdef CONFIG_NET_IPv6
+ /* Get the IPv6 address that we are binding to */
+
+ ipaddr = addr->sin6_addr.in6_u.u6_addr16;
+
+ /* Is the address IN6ADDR_ANY? */
+
+ if (net_ipaddr_cmp(ipaddr, g_in6addr_any))
+#else
+ /* Get the IPv4 address that we are binding to */
+
+ ipaddr = addr->sin_addr.s_addr;
+
+ /* Is the address INADDR_ANY? */
+
+ if (net_ipaddr_cmp(ipaddr, INADDR_ANY))
+#endif
+ {
+ /* Get the default device */
+
+ dev = netdev_default();
+ if (dev == NULL)
+ {
+ return -EADDRNOTAVAIL;
+ }
+
+ /* Use the IP address assigned to the default device */
+
+ ipaddr = dev->d_ipaddr;
+ }
+ else
+ {
+ /* We cannot bind the socket to an IP address if it cannot be routed
+ * by a registered network device.
+ */
+
+ dev = netdev_findbyaddr(ipaddr);
+ if (!dev)
+ {
+ return -EADDRNOTAVAIL;
+ }
+ }
/* Is the user requesting to bind to any port? */
if (!addr->sin_port)
{
- /* Yes.. Find an unused local port number */
+ /* Yes.. Select any unused local port number */
+#ifdef CONFIG_NETDEV_MULTINIC
+ conn->lport = htons(udp_select_port(ipaddr));
+#else
conn->lport = htons(udp_select_port());
+#endif
ret = OK;
}
else
@@ -397,9 +480,13 @@ int udp_bind(FAR struct udp_conn_s *conn, FAR const struct sockaddr_in *addr)
flags = net_lock();
- /* Is any other UDP connection already bound to this port? */
+ /* Is any other UDP connection already bound to this address and port? */
+#ifdef CONFIG_NETDEV_MULTINIC
+ if (!udp_find_conn(ipaddr, addr->sin_port))
+#else
if (!udp_find_conn(addr->sin_port))
+#endif
{
/* No.. then bind the socket to the port */
@@ -448,6 +535,39 @@ int udp_connect(FAR struct udp_conn_s *conn,
FAR const struct sockaddr_in *addr)
#endif
{
+#ifdef CONFIG_NETDEV_MULTINIC
+ FAR struct net_driver_s *dev;
+
+ /* Has this connection already been bound to a local IP address (lipaddr)? */
+
+#ifdef CONFIG_NET_IPv6
+ /* Is the address IN6ADDR_ANY? */
+
+ if (net_ipaddr_cmp(conn->lipaddr, g_in6addr_any))
+#else
+ /* Is the address INADDR_ANY? */
+
+ if (net_ipaddr_cmp(conn->lipaddr, INADDR_ANY))
+#endif
+ {
+ /* Get the default device */
+
+ dev = netdev_default();
+ if (dev == NULL)
+ {
+ return -EADDRNOTAVAIL;
+ }
+
+ /* Use the IP address assigned to the default device */
+
+ net_ipaddr_copy(conn->lipaddr, dev->d_ipaddr);
+
+ /* Make sure that we re-assign a valid port on this IP address */
+
+ conn->lport = 0;
+ }
+#endif /* CONFIG_NETDEV_MULTINIC */
+
/* Has this address already been bound to a local port (lport)? */
if (!conn->lport)
@@ -456,10 +576,14 @@ int udp_connect(FAR struct udp_conn_s *conn,
* connection structure.
*/
+#ifdef CONFIG_NETDEV_MULTINIC
+ conn->lport = htons(udp_select_port(conn->lipaddr));
+#else
conn->lport = htons(udp_select_port());
+#endif
}
- /* Is there a remote port (rport) */
+ /* Is there a remote port (rport)? */
if (addr)
{