diff options
-rw-r--r-- | include/net.h | 1 | ||||
-rw-r--r-- | net/net.c | 30 |
2 files changed, 29 insertions, 2 deletions
diff --git a/include/net.h b/include/net.h index b7555c0de6..3faecff5d7 100644 --- a/include/net.h +++ b/include/net.h @@ -226,6 +226,7 @@ IPaddr_t net_get_serverip(void); IPaddr_t net_get_gateway(void); IPaddr_t net_get_nameserver(void); const char *net_get_domainname(void); +struct eth_device *net_route(IPaddr_t ip); /* Do the work */ void net_poll(void); @@ -144,6 +144,27 @@ static void arp_handler(struct arprequest *arp) } } +struct eth_device *net_route(IPaddr_t dest) +{ + struct eth_device *edev; + + for_each_netdev(edev) { + if (!edev->ipaddr) + continue; + + if ((dest & edev->netmask) == (edev->ipaddr & edev->netmask)) { + pr_debug("Route: Using %s (ip=%pI4, nm=%pI4) to reach %pI4\n", + dev_name(&edev->dev), &edev->ipaddr, &edev->netmask, + &dest); + return edev; + } + } + + pr_debug("Route: No device found for %pI4\n", &dest); + + return NULL; +} + static int arp_request(struct eth_device *edev, IPaddr_t dest, unsigned char *ether) { char *pkt; @@ -154,6 +175,9 @@ static int arp_request(struct eth_device *edev, IPaddr_t dest, unsigned char *et unsigned retries = 0; int ret; + if (!edev) + return -EHOSTUNREACH; + if (!arp_packet) { arp_packet = net_alloc_packet(); if (!arp_packet) @@ -295,9 +319,11 @@ static struct net_connection *net_new(struct eth_device *edev, IPaddr_t dest, int ret; if (!edev) { - edev = eth_get_current(); + edev = net_route(dest); + if (!edev && net_gateway) + edev = net_route(net_gateway); if (!edev) - return ERR_PTR(-ENETDOWN); + return ERR_PTR(-EHOSTUNREACH); } if (!is_valid_ether_addr(edev->ethaddr)) { |