summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/nshlib/README.txt10
-rw-r--r--nuttx/ChangeLog6
-rw-r--r--nuttx/net/Makefile2
-rw-r--r--nuttx/net/net_route.h36
-rw-r--r--nuttx/net/net_router.c26
-rw-r--r--nuttx/net/netdev_router.c179
-rw-r--r--nuttx/net/uip/uip_arp.c17
7 files changed, 263 insertions, 13 deletions
diff --git a/apps/nshlib/README.txt b/apps/nshlib/README.txt
index 2c8c5f615..7a12ad4b4 100644
--- a/apps/nshlib/README.txt
+++ b/apps/nshlib/README.txt
@@ -242,6 +242,10 @@ o addroute <target> <netmask> <router>
to an external network characterized by the <target> IP address and
a network mask <netmask>
+ Example:
+
+ nsh> addroute 1.1.1.1 2.2.2.2 3.3.3.3
+
o base64dec [-w] [-f] <string or filepath>
o base64dec [-w] [-f] <string or filepath>
@@ -324,13 +328,17 @@ o dd if=<infile> of=<outfile> [bs=<sectsize>] [count=<sectors>] [skip=<sectors>]
brw-rw-rw- 0 ram0
nsh> dd if=/dev/ram0 of=/dev/null
-o delroute <target> <netmask> <router>
+o delroute <target> <netmask>
This command removes an entry from the routing table. The entry
removed will be the first entry in the routing table that matches
the external network characterized by the <target> IP address and
the network mask <netmask>
+ Example:
+
+ nsh> delroute 1.1.1.1 2.2.2.2
+
o df
Show the state of each mounted volume.
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 01b8965ee..8740afb4c 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -5708,4 +5708,8 @@
route, then it will simply return that single device. The
ARP logic will use the default router address associated with
the interface in this case (2013-10-5).
-
+ * net/netdev_router.c and net/uip/uip-arp.c: When the target IP address
+ does not lie on the device's networker when we have a routing table,
+ looking the the correct router IP address to use in the ARP request.
+ In that case, we want the MAC address of the router, not of the the
+ target endpoint (2013-10-5).
diff --git a/nuttx/net/Makefile b/nuttx/net/Makefile
index 07d3fb445..32c80b889 100644
--- a/nuttx/net/Makefile
+++ b/nuttx/net/Makefile
@@ -66,7 +66,7 @@ endif
ifeq ($(CONFIG_NET_ROUTE),y)
SOCK_CSRCS += net_addroute.c net_allocroute.c net_delroute.c
-SOCK_CSRCS += net_foreachroute.c net_router.c
+SOCK_CSRCS += net_foreachroute.c net_router.c netdev_router.c
endif
# Support for network access using streams
diff --git a/nuttx/net/net_route.h b/nuttx/net/net_route.h
index fec27698e..08039fe01 100644
--- a/nuttx/net/net_route.h
+++ b/nuttx/net/net_route.h
@@ -202,7 +202,41 @@ int net_delroute(uip_ipaddr_t target, uip_ipaddr_t netmask);
#ifdef CONFIG_NET_IPv6
int net_router(uip_ipaddr_t target, uip_ipaddr_t router);
#else
-int net_router(uip_ipaddr_t target, uip_ipaddr_t *router);
+int net_router(uip_ipaddr_t target, FAR uip_ipaddr_t *router);
+#endif
+
+/****************************************************************************
+ * Function: netdev_router
+ *
+ * Description:
+ * Given an IP address on a external network, return the address of the
+ * router on a local network that can forward to the external network.
+ * This is similar to net_router(). However, the set of routers is
+ * constrained to those accessible by the specific device
+ *
+ * Parameters:
+ * dev - We are committed to using this device.
+ * target - An IP address on a remote network to use in the lookup.
+ * router - The address of router on a local network that can forward our
+ * packets to the target.
+ *
+ * NOTE: For IPv6, router will be an array, for IPv4 it will be a scalar
+ * value. Hence, the change in the function signature.
+ *
+ * Returned Value:
+ * None, a router address is always returned (which may just be, perhaps,
+ * device's default router address)
+ *
+ ****************************************************************************/
+
+struct uip_driver_s;
+
+#ifdef CONFIG_NET_IPv6
+void netdev_router(FAR struct uip_driver_s *dev, uip_ipaddr_t target,
+ uip_ipaddr_t router);
+#else
+void netdev_router(FAR struct uip_driver_s *dev, uip_ipaddr_t target,
+ FAR uip_ipaddr_t *router);
#endif
/****************************************************************************
diff --git a/nuttx/net/net_router.c b/nuttx/net/net_router.c
index 71344f842..e56b2c550 100644
--- a/nuttx/net/net_router.c
+++ b/nuttx/net/net_router.c
@@ -79,7 +79,7 @@ struct route_match_s
static int net_match(FAR struct net_route_s *route, FAR void *arg)
{
- FAR struct route_match_s *match = ( FAR struct route_match_s *)arg;
+ FAR struct route_match_s *match = (FAR struct route_match_s *)arg;
/* To match, the masked target addresses must be the same. In the event
* of multiple matches, only the first is returned. There not (yet) any
@@ -124,7 +124,7 @@ static int net_match(FAR struct net_route_s *route, FAR void *arg)
#ifdef CONFIG_NET_IPv6
int net_router(uip_ipaddr_t target, uip_ipaddr_t router)
#else
-int net_router(uip_ipaddr_t target, uip_ipaddr_t *router)
+int net_router(uip_ipaddr_t target, FAR uip_ipaddr_t *router)
#endif
{
struct route_match_s match;
@@ -135,14 +135,28 @@ int net_router(uip_ipaddr_t target, uip_ipaddr_t *router)
memset(&match, 0, sizeof(struct route_match_s));
uip_ipaddr_copy(match.target, target);
- /* Then remove the entry from the routing table */
+ /* Find an router entry with the routing table that can forward to this
+ * address
+ */
+
+ ret = net_foreachroute(net_match, &match);
+ if (ret > 0)
+ {
+ /* We found a route. Return the router address. */
- ret = net_foreachroute(net_match, &match) ? OK : -ENOENT;
#ifdef CONFIG_NET_IPv6
- uip_ipaddr_copy(router, match.target);
+ uip_ipaddr_copy(router, match.target);
#else
- uip_ipaddr_copy(*router, match.target);
+ uip_ipaddr_copy(*router, match.target);
#endif
+ ret = OK;
+ }
+ else
+ {
+ /* There is no route for this address */
+
+ ret = -ENOENT;
+ }
return ret;
}
diff --git a/nuttx/net/netdev_router.c b/nuttx/net/netdev_router.c
new file mode 100644
index 000000000..d1026cac5
--- /dev/null
+++ b/nuttx/net/netdev_router.c
@@ -0,0 +1,179 @@
+/****************************************************************************
+ * net/netdev_router.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include <nuttx/net/uip/uip-arch.h>
+
+#include "net_internal.h"
+#include "net_route.h"
+
+#if defined(CONFIG_NET) && defined(CONFIG_NET_ROUTE)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+struct route_devmatch_s
+{
+ FAR struct uip_driver_s *dev; /* The route must use this device */
+ uip_ipaddr_t target; /* The target IP address on an external network to match */
+ uip_ipaddr_t router; /* The IP address of the router on one of our networks*/
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: net_devmatch
+ *
+ * Description:
+ * Return 1 if the route is available on the device's network.
+ *
+ * Parameters:
+ * route - The next route to examine
+ * arg - The match values (cast to void*)
+ *
+ * Returned Value:
+ * 0 if the entry is not a match; 1 if the entry matched and was cleared.
+ *
+ ****************************************************************************/
+
+static int net_devmatch(FAR struct net_route_s *route, FAR void *arg)
+{
+ FAR struct route_devmatch_s *match = (FAR struct route_devmatch_s *)arg;
+ FAR struct uip_driver_s *dev = match->dev;
+
+ /* To match, (1) the masked target addresses must be the same, and (2) the
+ * router address must like on the network provided by the device.
+ *
+ * In the event of multiple matches, only the first is returned. There
+ * not (yet) any concept for the precedence of networks.
+ */
+
+ if (uip_ipaddr_maskcmp(route->target, match->target, route->netmask) &&
+ uip_ipaddr_maskcmp(route->router, dev->d_ipaddr, dev->d_netmask))
+ {
+ /* They match.. Copy the router address */
+
+ uip_ipaddr_copy(match->router, route->router);
+ return 1;
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: netdev_router
+ *
+ * Description:
+ * Given an IP address on a external network, return the address of the
+ * router on a local network that can forward to the external network.
+ * This is similar to net_router(). However, the set of routers is
+ * constrained to those accessible by the specific device
+ *
+ * Parameters:
+ * dev - We are committed to using this device.
+ * target - An IP address on a remote network to use in the lookup.
+ * router - The address of router on a local network that can forward our
+ * packets to the target.
+ *
+ * NOTE: For IPv6, router will be an array, for IPv4 it will be a scalar
+ * value. Hence, the change in the function signature.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_IPv6
+void netdev_router(FAR struct uip_driver_s *dev, uip_ipaddr_t target,
+ uip_ipaddr_t router)
+#else
+void netdev_router(FAR struct uip_driver_s *dev, uip_ipaddr_t target,
+ FAR uip_ipaddr_t *router)
+#endif
+{
+ struct route_devmatch_s match;
+ int ret;
+
+ /* Set up the comparison structure */
+
+ memset(&match, 0, sizeof(struct route_devmatch_s));
+ match.dev = dev;
+ uip_ipaddr_copy(match.target, target);
+
+ /* Then remove the entry from the routing table */
+
+ ret = net_foreachroute(net_devmatch, &match);
+ if (ret > 0)
+ {
+ /* We found a route. Return the router address. */
+
+#ifdef CONFIG_NET_IPv6
+ uip_ipaddr_copy(router, match.target);
+#else
+ uip_ipaddr_copy(*router, match.target);
+#endif
+ ret = OK;
+ }
+ else
+ {
+ /* There isn't a matching route.. fallback and use the default router
+ * of the device.
+ */
+
+#ifdef CONFIG_NET_IPv6
+ uip_ipaddr_copy(router, dev->d_draddr);
+#else
+ uip_ipaddr_copy(*router, dev->d_draddr);
+#endif
+ }
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_ROUTE */
diff --git a/nuttx/net/uip/uip_arp.c b/nuttx/net/uip/uip_arp.c
index d9d1f0e04..e80c80dec 100644
--- a/nuttx/net/uip/uip_arp.c
+++ b/nuttx/net/uip/uip_arp.c
@@ -370,12 +370,23 @@ void uip_arp_out(struct uip_driver_s *dev)
destipaddr = uip_ip4addr_conv(pip->eh_destipaddr);
if (!uip_ipaddr_maskcmp(destipaddr, dev->d_ipaddr, dev->d_netmask))
{
- /* Destination address was not on the local network, so we need to
- * use the default router's IP address instead of the destination
- * address when determining the MAC address.
+ /* Destination address is not on the local network */
+
+#ifdef CONFIG_NET_ROUTE
+ /* We have a routing table.. find the correct router to use in
+ * this case (or, as a fallback, use the device's default router
+ * address). We will use the router IP address instead of the
+ * destination address when determining the MAC address.
+ */
+
+ netdev_router(dev, destipaddr, &ipaddr);
+#else
+ /* Use the device's default router IP address instead of the
+ * destination address when determining the MAC address.
*/
uip_ipaddr_copy(ipaddr, dev->d_draddr);
+#endif
}
else
{