diff --git a/fs/vfs/fs_pread.c b/fs/vfs/fs_pread.c index 24451a24545..03c1ec27c07 100644 --- a/fs/vfs/fs_pread.c +++ b/fs/vfs/fs_pread.c @@ -66,38 +66,32 @@ ssize_t file_pread(FAR struct file *filep, FAR void *buf, size_t nbytes, off_t savepos; off_t pos; ssize_t ret; - int errcode = 0; /* Perform the seek to the current position. This will not move the * file pointer, but will return its current setting */ savepos = file_seek(filep, 0, SEEK_CUR); - if (savepos == (off_t)-1) + if (savepos < 0) { /* file_seek might fail if this if the media is not seekable */ - return ERROR; + return (ssize_t)savepos; } /* Then seek to the correct position in the file */ pos = file_seek(filep, offset, SEEK_SET); - if (pos == (off_t)-1) + if (pos < 0) { /* This might fail is the offset is beyond the end of file */ - return ERROR; + return (ssize_t)pos; } /* Then perform the read operation */ ret = file_read(filep, buf, nbytes); - if (ret < 0) - { - errcode = -ret; - ret = ERROR; - } /* Restore the file position */ @@ -106,13 +100,7 @@ ssize_t file_pread(FAR struct file *filep, FAR void *buf, size_t nbytes, { /* This really should not fail */ - errcode = -pos; - ret = ERROR; - } - - if (errcode != 0) - { - set_errno(errcode); + ret = (ssize_t)pos; } return ret; @@ -170,6 +158,11 @@ ssize_t pread(int fd, FAR void *buf, size_t nbytes, off_t offset) /* Let file_pread do the real work */ ret = file_pread(filep, buf, nbytes, offset); + if (ret < 0) + { + set_errno((int)-ret); + ret = (ssize_t)ERROR; + } } leave_cancellation_point(); diff --git a/fs/vfs/fs_pwrite.c b/fs/vfs/fs_pwrite.c index 641649b02ef..ad7741b9d05 100644 --- a/fs/vfs/fs_pwrite.c +++ b/fs/vfs/fs_pwrite.c @@ -159,7 +159,7 @@ ssize_t pwrite(int fd, FAR const void *buf, size_t nbytes, off_t offset) if (ret < 0) { set_errno((int)-ret); - ret = ERROR; + ret = (ssize_t)ERROR; } } diff --git a/include/sys/stat.h b/include/sys/stat.h index 4d82f62d5e2..5d2d3f7fcc7 100644 --- a/include/sys/stat.h +++ b/include/sys/stat.h @@ -154,7 +154,7 @@ extern "C" int mkdir(FAR const char *pathname, mode_t mode); int mkfifo(FAR const char *pathname, mode_t mode); -int stat(const char *path, FAR struct stat *buf); +int stat(FAR const char *path, FAR struct stat *buf); int fstat(int fd, FAR struct stat *buf); #undef EXTERN diff --git a/net/route/Kconfig b/net/route/Kconfig index 5e1d60a3b2b..c927561ba5f 100644 --- a/net/route/Kconfig +++ b/net/route/Kconfig @@ -37,12 +37,23 @@ config ROUTE_IPv4_ROMROUTE NOTE: The read-only variable g_ipv4_nroutes must be set to the actual number of valid entries in the array. -config NET_ROUTE_IPv4_FILEROUTE +config ROUTE_IPv4_FILEROUTE bool "File" - depends on EXPERIMENTAL ---help--- Select to used a IPv4 routing table in a file in a mounted file system. + REVISIT: There is a problem with the current design. NuttX does not + currently support truncate(). Therefore, it is not possible to delete + entries from the routing table file. + + In this current implementation, that leaves the last entry intact at + the end of the file. An alternative design might include a tag on + each record to indicate if the record is valid or not. That would work + but would add complexity to the other routing table functions. + + The existing 'delroute' implementation is available for testing purpose + only if CONFIG_EXPERIMENTAL=y. + endchoice # IPv4 routing table config ROUTE_MAX_IPv4_RAMROUTES @@ -62,12 +73,12 @@ choice config ROUTE_IPv6_RAMROUTE bool "In-memory" ---help--- - Select to used a IPv6 routing table RAM. + Select to use a IPv6 routing table RAM. config ROUTE_IPv6_ROMROUTE bool "Read-only" ---help--- - Select to used a fixed read-only IPv6 routing table in FLASH or ROM. + Select to use a fixed read-only IPv6 routing table in FLASH or ROM. In this case, the board-specific logic must provide a routing table of the form of simply array: @@ -77,11 +88,22 @@ config ROUTE_IPv6_ROMROUTE NOTE: The read-only variable g_ipv6_nroutes must be set to the actual number of valid entries in the array. -config NET_ROUTE_IPv6_FILEROUTE +config ROUTE_IPv6_FILEROUTE bool "File" - depends on EXPERIMENTAL ---help--- - Select to used a IPv6 routing table in a file in a mounted file system. + Select to use a IPv6 routing table in a file in a mounted file system. + + REVISIT: There is a problem with the current design. NuttX does not + currently support truncate(). Therefore, it is not possible to delete + entries from the routing table file. + + In this current implementation, that leaves the last entry intact at + the end of the file. An alternative design might include a tag on + each record to indicate if the record is valid or not. That would work + but would add complexity to the other routing table functions. + + The existing 'delroute' implementation is available for testing purpose + only if CONFIG_EXPERIMENTAL=y. endchoice # IPv6 routing table @@ -94,5 +116,14 @@ config ROUTE_MAX_IPv6_RAMROUTES eliminates dynamica memory allocations, but limits the maximum size of the in-memory routing table to this number. +config ROUTE_FILEDIR + string "Routing table directory" + default /tmp + depends on ROUTE_IPv4_FILEROUTE || ROUTE_IPv6_FILEROUTE + ---help--- + Provides the full path to location in the file system where routing + table will be accessed. This is a string and should not include + any traling '/'. + endif # NET_ROUTE endmenu # ARP Configuration diff --git a/net/route/Make.defs b/net/route/Make.defs index b4e9bd0d349..5785be6a9c0 100644 --- a/net/route/Make.defs +++ b/net/route/Make.defs @@ -57,6 +57,16 @@ else ifeq ($(CONFIG_ROUTE_IPv6_ROMROUTE),y) SOCK_CSRCS += net_foreach_romroute.c endif +# Support for routing tables in files + +ifeq ($(CONFIG_ROUTE_IPv4_FILEROUTE),y) +SOCK_CSRCS += net_fileroute.c net_add_fileroute.c net_del_fileroute.c +SOCK_CSRCS += net_foreach_fileroute.c +else ifeq ($(CONFIG_ROUTE_IPv6_FILEROUTE),y) +SOCK_CSRCS += net_fileroute.c net_add_fileroute.c net_del_fileroute.c +SOCK_CSRCS += net_foreach_fileroute.c +endif + ifeq ($(CONFIG_DEBUG_NET_INFO),y) SOCK_CSRCS += net_dumproute.c endif diff --git a/net/route/fileroute.h b/net/route/fileroute.h new file mode 100644 index 00000000000..15d52f6d3dc --- /dev/null +++ b/net/route/fileroute.h @@ -0,0 +1,284 @@ +/**************************************************************************** + * net/route/fileroute.h + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ****************************************************************************/ + +#ifndef __NET_ROUTE_FILEROUTE_H +#define __NET_ROUTE_FILEROUTE_H 1 + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "route/route.h" + +#if defined(CONFIG_ROUTE_IPv4_FILEROUTE) || defined(CONFIG_ROUTE_IPv6_FILEROUTE) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define IPv4_ROUTE_PATH CONFIG_ROUTE_FILEDIR "/ipv4" +#define IPv6_ROUTE_PATH CONFIG_ROUTE_FILEDIR "/ipv6" + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +struct file; /* Forward reference */ + +/**************************************************************************** + * Name: net_init_fileroute + * + * Description: + * Initialize the in-memory, RAM routing table + * + * Parameters: + * None + * + * Returned Value: + * None + * + * Assumptions: + * Called early in initialization so that no special protection is needed. + * + ****************************************************************************/ + +void net_init_fileroute(void); + +/**************************************************************************** + * Name: net_openroute_ipv4/net_openroute_ipv6 + * + * Description: + * Open the IPv4/IPv6 routing table with the specified access privileges. + * + * Parameters: + * oflags - Open flags + * filep - Location in which to return the detached file instance. + * + * Returned Value: + * A non-negative file descriptor is returned on success. A negated errno + * value is returned on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +int net_openroute_ipv4(int oflags, FAR struct file *filep); +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +int net_openroute_ipv6(int oflags, FAR struct file *filep); +#endif + +/**************************************************************************** + * Name: net_readroute_ipv4/net_readroute_ipv6 + * + * Description: + * Read one route entry from the IPv4/IPv6 routing table. + * + * Parameters: + * filep - Detached file instance obtained by net_openroute_ipv{4|6}[_rdonly] + * route - Location to return the next route read from the file + * + * Returned Value: + * The number of bytes read on success. The special return valud of zero + * indiates that the endof of file was encountered (and nothing was read). + * A negated errno value is returned on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +ssize_t net_readroute_ipv4(FAR struct file *filep, + FAR struct net_route_ipv4_s *route); +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +ssize_t net_readroute_ipv6(FAR struct file *filep, + FAR struct net_route_ipv6_s *route); +#endif + +/**************************************************************************** + * Name: net_writeroute_ipv4/net_writeroute_ipv6 + * + * Description: + * Write one route entry to the IPv4/IPv6 routing table. + * + * Parameters: + * filep - Detached file instance obtained by net_openroute_ipv{4|6}[_rdonly] + * route - Location to return the next route read from the file + * + * Returned Value: + * The number of bytes written on success. A negated errno value is + * returned on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +ssize_t net_writeroute_ipv4(FAR struct file *filep, + FAR const struct net_route_ipv4_s *route); +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +ssize_t net_writeroute_ipv6(FAR struct file *filep, + FAR const struct net_route_ipv6_s *route); +#endif + +/**************************************************************************** + * Name: net_seekroute_ipv4/net_seekroute_ipv6 + * + * Description: + * Seek to a specific entry entry to the IPv4/IPv6 routing table. + * + * Parameters: + * filep - Detached file instance obtained by net_openroute_ipv{4|6}[_rdonly] + * index - The index of the routing table entry to seek to. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +off_t net_seekroute_ipv4(FAR struct file *filep, unsigned int index); +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +off_t net_seekroute_ipv6(FAR struct file *filep, unsigned int index); +#endif + +/**************************************************************************** + * Name: net_routesize_ipv4/net_routesize_ipv6 + * + * Description: + * Return the size of a routing table in terms of the number of entries in + * the routing table. + * + * Parameters: + * None + * + * Returned Value: + * A non-negative count of the number of entries in the routing table is + * returned on success; a negated errno value is returned on and failure. + * + * Assumptions: + * The size of the routing table may change after this size is returned + * unless the routing table is locked to prevent any modification to the + * routing table. + * + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +int net_routesize_ipv4(void); +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +int net_routesize_ipv6(void); +#endif + +/**************************************************************************** + * Name: net_lockroute_ipv4/net_lockroute_ipv6 + * + * Description: + * Lock access to the routing table. Necessary when a routing table is + * being reorganized due to deletion of a route. + * + * Parameters: + * None + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +int net_lockroute_ipv4(void); +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +int net_lockroute_ipv6(void); +#endif + +/**************************************************************************** + * Name: net_unlockroute_ipv4/net_unlockroute_ipv6 + * + * Description: + * Release the read lock. + * + * Parameters: + * None + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +int net_unlockroute_ipv4(void); +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +int net_unlockroute_ipv6(void); +#endif + +/**************************************************************************** + * Name: net_closeroute_ipv4/net_closeroute_ipv6 + * + * Description: + * Close the IPv4/IPv6 routing table. + * + * Parameters: + * filep - Detached file instance obtained by net_openroute_ipv{4|6}[_rdonly] + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +int net_closeroute_ipv4(FAR struct file *filep); +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +int net_closeroute_ipv6(FAR struct file *filep); +#endif + +#endif /* CONFIG_ROUTE_IPv4_FILEROUTE || CONFIG_ROUTE_IPv6_FILEROUTE */ +#endif /* __NET_ROUTE_FILEROUTE_H */ diff --git a/net/route/net_add_fileroute.c b/net/route/net_add_fileroute.c new file mode 100644 index 00000000000..74fb2fdafc1 --- /dev/null +++ b/net/route/net_add_fileroute.c @@ -0,0 +1,141 @@ +/**************************************************************************** + * net/route/net_add_fileroute.c + * + * Copyright (C) 2013, 2015, 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include + +#include +//#include +#include + +#include "route/fileroute.h" +#include "route/route.h" + +#if defined(CONFIG_ROUTE_IPv4_FILEROUTE) || defined(CONFIG_ROUTE_IPv6_FILEROUTE) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_addroute_ipv4 and net_addroute_ipv6 + * + * Description: + * Add a new route to the routing table + * + * Parameters: + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +int net_addroute_ipv4(in_addr_t target, in_addr_t netmask, in_addr_t router) +{ + struct net_route_ipv4_s route; + struct file fshandle; + ssize_t nwritten; + int ret; + + /* Format the new routing table entry */ + + net_ipv4addr_copy(route.target, target); + net_ipv4addr_copy(route.netmask, netmask); + net_ipv4addr_copy(route.router, router); + net_ipv4_dumproute("New route", &route); + + /* Open the IPv4 routing table for append access */ + + ret = net_openroute_ipv4(O_WRONLY | O_APPEND | O_CREAT, &fshandle); + if (ret < 0) + { + nerr("ERROR: Could not open IPv4 routing table: %d\n", ret); + return ret; + } + + /* Then append the new entry to the end of the routing table */ + + nwritten = net_writeroute_ipv4(&fshandle, &route); + + (void)net_closeroute_ipv4(&fshandle); + return nwritten >= 0 ? 0 : (int)nwritten; +} +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +int net_addroute_ipv6(net_ipv6addr_t target, net_ipv6addr_t netmask, + net_ipv6addr_t router) +{ + struct net_route_ipv6_s route; + struct file fshandle; + ssize_t nwritten; + int ret; + + /* Format the new routing table entry */ + + net_ipv6addr_copy(route.target, target); + net_ipv6addr_copy(route.netmask, netmask); + net_ipv6addr_copy(route.router, router); + net_ipv6_dumproute("New route", &route); + + /* Open the IPv6 routing table for append access */ + + ret = net_openroute_ipv6(O_WRONLY | O_APPEND | O_CREAT, &fshandle); + if (ret < 0) + { + nerr("ERROR: Could not open IPv6 routing table: %d\n", ret); + return ret; + } + + /* Then append the new entry to the end of the routing table */ + + nwritten = net_writeroute_ipv6(&fshandle, &route); + + (void)net_closeroute_ipv6(&fshandle); + return nwritten >= 0 ? 0 : (int)nwritten; +} +#endif + +#endif /* CONFIG_ROUTE_IPv4_FILEROUTE || CONFIG_ROUTE_IPv6_FILEROUTE */ diff --git a/net/route/net_del_fileroute.c b/net/route/net_del_fileroute.c new file mode 100644 index 00000000000..056506d41e9 --- /dev/null +++ b/net/route/net_del_fileroute.c @@ -0,0 +1,495 @@ +/**************************************************************************** + * net/route/net_del_fileroute.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "route/fileroute.h" +#include "route/route.h" + +#if defined(CONFIG_ROUTE_IPv4_FILEROUTE) || defined(CONFIG_ROUTE_IPv6_FILEROUTE) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* REVISIT: There is a problem with this design. NuttX does not currently + * support truncate(). Therefore, it is not possible to delete entries from + * the routing table file. + * + * In this current implementation, that leaves the last entry intact at the + * end of the file. An alternative design might include a tag on each + * record to indicate if the record is valid or not. That would work but + * would add complexity to the other routing table functions. + * + * The existing implementation is available only if CONFIG_EXPERIMENTAL=y. + */ + +#ifdef CONFIG_EXPERIMENTAL +# warning The implementation of delroute is incomplete +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +struct route_match_ipv4_s +{ + in_addr_t target; /* The target IP address to match */ + in_addr_t netmask; /* The network mask to match */ + unsigned int index; /* Index of match */ +}; +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +struct route_match_ipv6_s +{ + net_ipv6addr_t target; /* The target IP address to match */ + net_ipv6addr_t netmask; /* The network mask to match */ + unsigned int index; /* Index of match */ +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_match_ipv4 + * + * Description: + * Return 1 if the route is available + * + * 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. + * + ****************************************************************************/ + +#ifdef CONFIG_EXPERIMENTAL +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +static int net_match_ipv4(FAR struct net_route_ipv4_s *route, FAR void *arg) +{ + FAR struct route_match_ipv4_s *match = (FAR struct route_match_ipv4_s *)arg; + + /* To match, the masked target address must be the same, and the masks + * must be the same. + */ + + net_ipv4_dumproute("Comparing", route); + ninfo("With:\n"); + ninfo(" target=%08lx netmask=%08lx\n", + htonl(match->target), htonl(match->netmask)); + + if (net_ipv4addr_maskcmp(route->target, match->target, match->netmask) && + net_ipv4addr_cmp(route->netmask, match->netmask)) + { + /* They match.. a non-zero value to terminate the traversal. The last + * value of index is the index to the matching entry. + */ + + return 1; + } + + /* Next time we are here, this will be the routing table index */ + + match->index++; + return 0; +} +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +static int net_match_ipv6(FAR struct net_route_ipv6_s *route, FAR void *arg) +{ + FAR struct route_match_ipv6_s *match = (FAR struct route_match_ipv6_s *)arg; + + /* To match, the masked target address must be the same, and the masks + * must be the same. + */ + + net_ipv6_dumproute("Comparing", route); + ninfo("With:\n"); + ninfo(" target: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + htons(match->target[0]), htons(match->target[1]), + htons(match->target[2]), htons(match->target[3]), + htons(match->target[4]), htons(match->target[5]), + htons(match->target[6]), htons(match->target[7])); + ninfo(" netmask: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + htons(match->netmask[0]), htons(match->netmask[1]), + htons(match->netmask[2]), htons(match->netmask[3]), + htons(match->netmask[4]), htons(match->netmask[5]), + htons(match->netmask[6]), htons(match->netmask[7])); + + if (net_ipv6addr_maskcmp(route->target, match->target, match->netmask) && + net_ipv6addr_cmp(route->netmask, match->netmask)) + { + /* They match.. a non-zero value to terminate the traversal. The last + * value of index is the index to the matching entry. + */ + + return 1; + } + + /* Next time we are here, this will be the routing table index */ + + match->index++; + return 0; +} +#endif +#endif /* CONFIG_EXPERIMENTAL */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_delroute_ipv4 and net_delroute_ipv6 + * + * Description: + * Remove an existing route from the routing table + * + * Parameters: + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +int net_delroute_ipv4(in_addr_t target, in_addr_t netmask) +{ +#ifdef CONFIG_EXPERIMENTAL + struct route_match_ipv4_s match; + struct net_route_ipv4_s route; + struct file fshandle; + ssize_t nwritten; + ssize_t nread; + off_t pos; + int nentries; + int index; + int ret; + + /* We must lock out other accesses to the routing table while we remove + * entry + */ + + ret = net_lockroute_ipv4(); + if (ret < 0) + { + nerr("ERROR: net_lockroute_ipv4 failed: %d\n", ret); + return ret; + } + + /* Get the size of the routing table entry (in entries) */ + + nentries = net_routesize_ipv4(); + if (nentries < 0) + { + ret = nentries; + goto errout_with_lock; + } + else if (nentries == 0) + { + ret = -ENOENT; + goto errout_with_lock; + } + + /* Set up the comparison structure */ + + net_ipv4addr_copy(match.target, target); + net_ipv4addr_copy(match.netmask, netmask); + match.index = 0; + + /* Then find the index into the routing table where the match can be found */ + + ret = net_foreachroute_ipv4(net_match_ipv4, &match); + if (ret < 0) + { + /* And error occurred */ + + goto errout_with_lock; + } + else if (ret == 0) + { + /* No match found */ + + ret = -ENOENT; + goto errout_with_lock; + } + + /* Open the routing table for read/write access */ + + ret = net_openroute_ipv4(O_RDWR, &fshandle); + if (ret < 0) + { + nerr("ERROR: Could not open IPv4 routing table: %d\n", ret); + goto errout_with_lock; + } + + /* Loop, copying each entry, to the previous entry thus removing the entry + * to be deleted. + */ + + for (index = match.index + 1; index < nentries; index++) + { + /* Seek to the current entry to be moved */ + + pos = net_seekroute_ipv4(&fshandle, index); + if (pos < 0) + { + nerr("ERROR: net_readroute_ipv4 failed: %ld\n", (long)pos); + ret =(int)pos; + goto errout_with_fshandle; + } + + /* Read the routing table entry at this position */ + + nread = net_readroute_ipv4(&fshandle, &route); + if (nread < 0) + { + nerr("ERROR: net_readroute_ipv4 failed: %ld\n", (long)nread); + ret = (int)nread; + goto errout_with_fshandle; + } + else if (nread == 0) + { + nerr("ERROR: Undexpected end of file\n"); + ret = -EINVAL; + goto errout_with_fshandle; + } + + /* Seek to the previous entry to be replaced */ + + pos = net_seekroute_ipv4(&fshandle, index - 1); + if (pos < 0) + { + nerr("ERROR: net_readroute_ipv4 failed: %ld\n", (long)pos); + ret =(int)pos; + goto errout_with_fshandle; + } + + /* Now write the record to its new location */ + + nwritten = net_writeroute_ipv4(&fshandle, &route); + if (nwritten < 0) + { + nerr("ERROR: net_readroute_ipv4 failed: %ld\n", (long)nwritten); + ret = (int)nwritten; + goto errout_with_fshandle; + } + } + + /* Now truncate the one duplicate entry at the end of the file. This may + * result in a zero length file. + */ +#warning Missing logic + + ret = OK; + +errout_with_fshandle: + (void)net_closeroute_ipv4(&fshandle); + +errout_with_lock: + (void)net_unlockroute_ipv4(); + return ret; +#else + return -ENOSYS; +#endif +} +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +int net_delroute_ipv6(net_ipv6addr_t target, net_ipv6addr_t netmask) +{ +#ifdef CONFIG_EXPERIMENTAL + struct route_match_ipv6_s match; + struct net_route_ipv6_s route; + struct file fshandle; + ssize_t nwritten; + ssize_t nread; + off_t pos; + int nentries; + int index; + int ret; + + /* We must lock out other accesses to the routing table while we remove + * entry + */ + + ret = net_lockroute_ipv6(); + if (ret < 0) + { + nerr("ERROR: net_lockroute_ipv6 failed: %d\n", ret); + return ret; + } + + /* Get the size of the routing table entry (in entries) */ + + nentries = net_routesize_ipv6(); + if (nentries < 0) + { + ret = nentries; + goto errout_with_lock; + } + else if (nentries == 0) + { + ret = -ENOENT; + goto errout_with_lock; + } + + /* Set up the comparison structure */ + + net_ipv6addr_copy(match.target, target); + net_ipv6addr_copy(match.netmask, netmask); + match.index = 0; + + /* Then find the index into the routing table where the match can be found */ + + ret = net_foreachroute_ipv6(net_match_ipv6, &match); + if (ret < 0) + { + /* And error occurred */ + + ret = ret; + goto errout_with_lock; + } + else if (ret == 0) + { + /* No match found */ + + ret = -ENOENT; + goto errout_with_lock; + } + + /* Open the routing table for read/write access */ + + ret = net_openroute_ipv6(O_RDWR, &fshandle); + if (ret < 0) + { + nerr("ERROR: Could not open IPv6 routing table: %d\n", ret); + goto errout_with_lock; + } + + /* Loop, copying each entry, to the previous entry thus removing the entry + * to be deleted. + */ + + for (index = match.index + 1; index < nentries; index++) + { + /* Seek to the current entry to be moved */ + + pos = net_seekroute_ipv6(&fshandle, index); + if (pos < 0) + { + nerr("ERROR: net_readroute_ipv6 failed: %ld\n", (long)pos); + ret =(int)pos; + goto errout_with_fshandle; + } + + /* Read the routing table entry at this position */ + + nread = net_readroute_ipv6(&fshandle, &route); + if (nread < 0) + { + nerr("ERROR: net_readroute_ipv6 failed: %ld\n", (long)nread); + ret = (int)nread; + goto errout_with_fshandle; + } + else if (nread == 0) + { + nerr("ERROR: Undexpected end of file\n"); + ret = -EINVAL; + goto errout_with_fshandle; + } + + /* Seek to the previous entry to be replaced */ + + pos = net_seekroute_ipv6(&fshandle, index - 1); + if (pos < 0) + { + nerr("ERROR: net_readroute_ipv6 failed: %ld\n", (long)pos); + ret =(int)pos; + goto errout_with_fshandle; + } + + /* Now write the record to its new location */ + + nwritten = net_writeroute_ipv6(&fshandle, &route); + if (nwritten < 0) + { + nerr("ERROR: net_readroute_ipv6 failed: %ld\n", (long)nwritten); + ret = (int)nwritten; + goto errout_with_fshandle; + } + } + + /* Now truncate the one duplicate entry at the end of the file. This may + * result in a zero length file. + */ +#warning Missing logic + + ret = OK; + +errout_with_fshandle: + (void)net_closeroute_ipv6(&fshandle); + +errout_with_lock: + (void)net_unlockroute_ipv6(); + return ret; +#else + return -ENOSYS; +#endif +} +#endif + +#endif /* CONFIG_ROUTE_IPv4_FILEROUTE || CONFIG_ROUTE_IPv6_FILEROUTE */ diff --git a/net/route/net_del_ramroute.c b/net/route/net_del_ramroute.c index 0646fccfbcc..06dc67e2f2f 100644 --- a/net/route/net_del_ramroute.c +++ b/net/route/net_del_ramroute.c @@ -57,11 +57,11 @@ ****************************************************************************/ #ifdef CONFIG_ROUTE_IPv4_RAMROUTE -struct route_match_s +struct route_match_ipv4_s { FAR struct net_route_ipv4_s *prev; /* Predecessor in the list */ - in_addr_t target; /* The target IP address to match */ - in_addr_t netmask; /* The network mask to match */ + in_addr_t target; /* The target IP address to match */ + in_addr_t netmask; /* The network mask to match */ }; #endif @@ -96,7 +96,7 @@ struct route_match_ipv6_s #ifdef CONFIG_ROUTE_IPv4_RAMROUTE static int net_match_ipv4(FAR struct net_route_ipv4_s *route, FAR void *arg) { - FAR struct route_match_s *match = (FAR struct route_match_s *)arg; + FAR struct route_match_ipv4_s *match = (FAR struct route_match_ipv4_s *)arg; /* To match, the masked target address must be the same, and the masks * must be the same. @@ -211,7 +211,7 @@ static int net_match_ipv6(FAR struct net_route_ipv6_s *route, FAR void *arg) #ifdef CONFIG_ROUTE_IPv4_RAMROUTE int net_delroute_ipv4(in_addr_t target, in_addr_t netmask) { - struct route_match_s match; + struct route_match_ipv4_s match; /* Set up the comparison structure */ diff --git a/net/route/net_fileroute.c b/net/route/net_fileroute.c new file mode 100644 index 00000000000..c40dcc5b39e --- /dev/null +++ b/net/route/net_fileroute.c @@ -0,0 +1,786 @@ +/**************************************************************************** + * net/route/net_fileroute.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "route/fileroute.h" +#include "route/route.h" + +#if defined(CONFIG_ROUTE_IPv4_FILEROUTE) || defined(CONFIG_ROUTE_IPv6_FILEROUTE) + +/**************************************************************************** + * Pre-processor Defintions + ****************************************************************************/ + +/* Special "impossible" PID value used to indicate that there is no holder + * of the lock. + */ + +#define NO_HOLDER ((pid_t)-1) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +/* Semaphore used to lock a routing table for exclusive write-only access */ + +static sem_t g_ipv4_exclsem; +static pid_t g_ipv4_holder = NO_HOLDER; +static int g_ipv4_count; +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +/* Semaphore used to lock a routing table for exclusive write-only access */ + +static sem_t g_ipv6_exclsem; +static pid_t g_ipv6_holder = NO_HOLDER; +static int g_ipv6_count; +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_openroute_detached + * + * Description: + * Open and detach the routing table. + * + * Parameters: + * pathname - The full path to the routing table entry + * oflags - Open flags + * filep - Location in which to return the detached file instance. + * + * Returned Value: + * A non-negative file descriptor is returned on success. A negated errno + * value is returned on any failure. + * + ****************************************************************************/ + +int net_openroute_detached(FAR const char *pathname, int oflags, + FAR struct file *filep) +{ + int ret; + int fd; + + /* Open the file for read/write access. Here we borrow the file descriptor + * of this tread of execution. We won't use it for long. + */ + + fd = open(pathname, oflags, 0644); + if (fd < 0) + { + int errcode = get_errno(); + nerr("ERROR: Failed to open %s: %d\n", pathname, errcode); + return -errcode; + } + + /* Now detach the file descriptor */ + + ret = file_detach(fd, filep); + if (ret < 0) + { + nerr("ERROR: file_detach() failed: %d\n", ret); + (void)close(fd); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: net_routesize + * + * Description: + * Return the size of a routing table in terms of the number of entries in + * the routing table. + * + * Parameters: + * path - The path to the routing table + * entrysize - The size of one entry in the routing table + * + * Returned Value: + * A non-negative count of the number of entries in the routing table is + * returned on success; a negated errno value is returned on and failure. + * + ****************************************************************************/ + +int net_routesize(FAR const char *path, size_t entrysize) +{ + struct stat buf; + int ret; + + /* Get information about the file */ + + ret = stat(path, &buf); + if (ret < 0) + { + int errcode; + + /* stat() failed, but is that because the routing table has not been + * created yet? + */ + + errcode = errno; + if (errcode == ENOENT) + { + /* The routing table file has not been created. Return size zero. */ + + return 0; + } + + /* Some other error */ + + return -errcode; + } + + /* The directory entry at this path must be a regular file */ + + if (S_ISREG(buf.st_mode)) + { + unsigned int nentries = buf.st_size / entrysize; + +#ifdef CONFIG_DEBUG_NET_WARN + if (nentries * entrysize != buf.st_size) + { + nwarn("WARNING: Size of routing table is not an even mutliple of entries\n"); + nwarn(" %lu != %lu / %lu\n", + (unsigned long)nentries, + (unsigned long)buf.st_size, + (unsigned long)entrysize); + } +#endif + + return nentries; + } + + /* It is probably a directory (should check for sure) */ + + return -EISDIR; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_init_fileroute + * + * Description: + * Initialize the in-memory, RAM routing table + * + * Parameters: + * None + * + * Returned Value: + * None + * + * Assumptions: + * Called early in initialization so that no special protection is needed. + * + ****************************************************************************/ + +void net_init_fileroute(void) +{ + /* Initialize semaphores */ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE + sem_init(&g_ipv4_exclsem, 0, 1); +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE + sem_init(&g_ipv6_exclsem, 0, 1); +#endif +} + +/**************************************************************************** + * Name: net_openroute_ipv4/net_openroute_ipv6 + * + * Description: + * Open the IPv4/IPv6 routing table with the specified access privileges. + * + * Parameters: + * oflags - Open flags + * filep - Location in which to return the detached file instance. + * + * Returned Value: + * A non-negative file descriptor is returned on success. A negated errno + * value is returned on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +int net_openroute_ipv4(int oflags, FAR struct file *filep) +{ + int ret; + + /* Lock the route.. we don't want to open it while it is subject to + * modification. + */ + + ret = net_lockroute_ipv4(); + if (ret < 0) + { + nerr("ERROR: net_lockroute_ipv4() failed: %d\n", ret); + } + else + { + /* Open the file for read/write access. */ + + ret = net_openroute_detached(IPv4_ROUTE_PATH, oflags, filep); + if (ret < 0) + { + nerr("ERROR: net_openroute_detached() failed: %d\n", ret); + } + } + + (void)net_unlockroute_ipv4(); + return ret; +} +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +int net_openroute_ipv6(int oflags, FAR struct file *filep) +{ + int ret; + + /* Lock the route.. we don't want to open it while it is subject to + * modification. + */ + + ret = net_lockroute_ipv6(); + if (ret < 0) + { + nerr("ERROR: net_lockroute_ipv6() failed: %d\n", ret); + } + else + { + /* Open the file for read/write access. */ + + ret = net_openroute_detached(IPv6_ROUTE_PATH, oflags, filep); + if (ret < 0) + { + nerr("ERROR: net_openroute_detached() failed: %d\n", ret); + } + } + + (void)net_unlockroute_ipv6(); + return ret; +} +#endif + +/**************************************************************************** + * Name: net_readroute_ipv4/net_readroute_ipv6 + * + * Description: + * Read one route entry from the IPv4/IPv6 routing table. + * + * Parameters: + * filep - Detached file instance obtained by net_openroute_ipv{4|6}[_rdonly] + * route - Location to return the next route read from the file + * + * Returned Value: + * The number of bytes read on success. The special return valud of zero + * indiates that the endof of file was encountered (and nothing was read). + * A negated errno value is returned on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +ssize_t net_readroute_ipv4(FAR struct file *filep, + FAR struct net_route_ipv4_s *route) +{ + ssize_t ret; + + /* Lock the route.. we don't want to read from it while it is subject to + * modification. + */ + + ret = (ssize_t)net_lockroute_ipv4(); + if (ret < 0) + { + nerr("ERROR: net_lockroute_ipv4() failed: %d\n", ret); + } + else + { + /* Read one record from the current position in the routing table */ + + ret = file_read(filep, route, sizeof(struct net_route_ipv4_s)); + } + + (void)net_unlockroute_ipv4(); + return ret; +} +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +ssize_t net_readroute_ipv6(FAR struct file *filep, + FAR struct net_route_ipv6_s *route) +{ + ssize_t ret; + + /* Lock the route.. we don't want to read from it while it is subject to + * modification. + */ + + ret = (ssize_t)net_lockroute_ipv6(); + if (ret < 0) + { + nerr("ERROR: net_lockroute_ipv6() failed: %d\n", ret); + } + else + { + /* Read one record from the current position in the routing table */ + + ret = file_read(filep, route, sizeof(struct net_route_ipv6_s)); + } + + (void)net_unlockroute_ipv6(); + return ret; +} +#endif + +/**************************************************************************** + * Name: net_writeroute_ipv4/net_writeroute_ipv6 + * + * Description: + * Write one route entry to the IPv4/IPv6 routing table. + * + * Parameters: + * filep - Detached file instance obtained by net_openroute_ipv{4|6}[_rdonly] + * route - Location to return the next route read from the file + * + * Returned Value: + * The number of bytes written on success. A negated errno value is + * returned on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +ssize_t net_writeroute_ipv4(FAR struct file *filep, + FAR const struct net_route_ipv4_s *route) +{ + ssize_t ret; + + /* Lock the route.. we don't want to write to it while it is subject to + * modification. + */ + + ret = (ssize_t)net_lockroute_ipv4(); + if (ret < 0) + { + nerr("ERROR: net_lockroute_ipv4() failed: %d\n", ret); + } + else + { + /* Write one record at the current position in the routing table */ + + ret = file_write(filep, route, sizeof(struct net_route_ipv4_s)); + } + + (void)net_unlockroute_ipv4(); + return ret; +} +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +ssize_t net_writeroute_ipv6(FAR struct file *filep, + FAR const struct net_route_ipv6_s *route) +{ + ssize_t ret; + + /* Lock the route.. we don't want to write to it while it is subject to + * modification. + */ + + ret = (ssize_t)net_lockroute_ipv6(); + if (ret < 0) + { + nerr("ERROR: net_lockroute_ipv6() failed: %d\n", ret); + } + else + { + /* Write one record at the current position in the routing table */ + + ret = file_write(filep, route, sizeof(struct net_route_ipv6_s)); + } + + (void)net_unlockroute_ipv6(); + return ret; +} +#endif + +/**************************************************************************** + * Name: net_seekroute_ipv4/net_seekroute_ipv6 + * + * Description: + * Seek to a specific entry entry to the IPv4/IPv6 routing table. + * + * Parameters: + * filep - Detached file instance obtained by net_openroute_ipv{4|6}[_rdonly] + * index - The index of the routing table entry to seek to. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +off_t net_seekroute_ipv4(FAR struct file *filep, unsigned int index) +{ + off_t offset; + off_t ret; + + /* Convert the index to a file offset */ + + offset = (off_t)index * sizeof(struct net_route_ipv4_s); + + /* Then seek to that position */ + + ret = file_seek(filep, offset, SEEK_SET); + if (ret < 0) + { + nerr("ERROR: file_seek() failed: %ld\n", (long)ret); + return (int)ret; + } + + return OK; +} +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +off_t net_seekroute_ipv6(FAR struct file *filep, unsigned int index) +{ + off_t offset; + off_t ret; + + /* Convert the index to a file offset */ + + offset = (off_t)index * sizeof(struct net_route_ipv6_s); + + /* Then seek to that position */ + + ret = file_seek(filep, offset, SEEK_SET); + if (ret < 0) + { + nerr("ERROR: file_seek() failed: %ld\n", (long)ret); + return (int)ret; + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: net_routesize_ipv4/net_routesize_ipv6 + * + * Description: + * Return the size of a routing table in terms of the number of entries in + * the routing table. + * + * Parameters: + * None + * + * Returned Value: + * A non-negative count of the number of entries in the routing table is + * returned on success; a negated errno value is returned on and failure. + * + * Assumptions: + * The size of the routing table may change after this size is returned + * unless the routing table is locked to prevent any modification to the + * routing table. + * + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +int net_routesize_ipv4(void) +{ + return net_routesize(IPv4_ROUTE_PATH, sizeof(struct net_route_ipv4_s)); +} +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +int net_routesize_ipv6(void) +{ + return net_routesize(IPv6_ROUTE_PATH, sizeof(struct net_route_ipv6_s)); +} +#endif + +/**************************************************************************** + * Name: net_lockroute_ipv4/net_lockroute_ipv6 + * + * Description: + * Lock access to the routing table. Necessary when a routing table is + * being reorganized due to deletion of a route. + * + * Parameters: + * None + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +int net_lockroute_ipv4(void) +{ + pid_t me = getpid(); + int ret; + + /* Are we already the holder of the lock? */ + + if (g_ipv4_holder == me) + { + /* Yes.. just increment the count of locks held */ + + g_ipv4_count++; + ret = OK; + } + else + { + /* No.. wait to get the lock */ + + ret = sem_wait(&g_ipv4_exclsem); + if (ret < 0) + { + int errcode = get_errno(); + nerr("ERROR: sem_wait() failed: %d\n", errcode); + ret = -errcode; + } + else + { + DEBUGASSERT(g_ipv4_holder == NO_HOLDER && g_ipv4_count == 0); + + /* We are now the holder with one count */ + + g_ipv4_holder = me; + g_ipv4_count = 1; + } + } + + return ret; +} +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +int net_lockroute_ipv6(void) +{ + pid_t me = getpid(); + int ret; + + /* Are we already the holder of the lock? */ + + if (g_ipv6_holder == me) + { + /* Yes.. just increment the count of locks held */ + + g_ipv6_count++; + ret = OK; + } + else + { + /* No.. wait to get the lock */ + + ret = sem_wait(&g_ipv6_exclsem); + if (ret < 0) + { + int errcode = get_errno(); + nerr("ERROR: sem_wait() failed: %d\n", errcode); + ret = -errcode; + } + else + { + DEBUGASSERT(g_ipv6_holder == NO_HOLDER && g_ipv6_count == 0); + + /* We are now the holder with one count */ + + g_ipv6_holder = me; + g_ipv6_count = 1; + } + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: net_unlockroute_ipv4/net_unlockroute_ipv6 + * + * Description: + * Release the read lock. + * + * Parameters: + * None + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +int net_unlockroute_ipv4(void) +{ + pid_t me = getpid(); + int ret; + + /* If would be an error if we are called with on a thread that does not + * hold the lock. + */ + + DEBUGASSERT(me == g_ipv4_holder && g_ipv4_count > 0); + + /* Release the count on the lock. If this is the last count, then release + * the lock. + */ + + if (g_ipv4_count > 1) + { + /* Not the last count... just decrement the count and return success */ + + g_ipv4_count--; + ret = OK; + } + else + { + /* This is the last count. Release the lock */ + + g_ipv4_holder = NO_HOLDER; + g_ipv4_count = 0; + + ret = sem_post(&g_ipv4_exclsem); + if (ret < 0) + { + int errcode = get_errno(); + nerr("ERROR: sem_post() failed: %d\n", errcode); + ret = -errcode; + } + } + + return ret; +} +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +int net_unlockroute_ipv6(void) +{ + pid_t me = getpid(); + int ret; + + /* If would be an error if we are called with on a thread that does not + * hold the lock. + */ + + DEBUGASSERT(me == g_ipv6_holder && g_ipv6_count > 0); + + /* Release the count on the lock. If this is the last count, then release + * the lock. + */ + + if (g_ipv6_count > 1) + { + /* Not the last count... just decrement the count and return success */ + + g_ipv6_count--; + ret = OK; + } + else + { + /* This is the last count. Release the lock */ + + g_ipv6_holder = NO_HOLDER; + g_ipv6_count = 0; + + ret = sem_post(&g_ipv6_exclsem); + if (ret < 0) + { + int errcode = get_errno(); + nerr("ERROR: sem_post() failed: %d\n", errcode); + ret = -errcode; + } + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: net_closeroute_ipv4/net_closeroute_ipv6 + * + * Description: + * Close the IPv4/IPv6 routing table. + * + * Parameters: + * filep - Detached file instance obtained by net_openroute_ipv{4|6}[_rdonly] + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +int net_closeroute_ipv4(FAR struct file *filep) +{ + return file_close_detached(filep); +} +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +int net_closeroute_ipv6(FAR struct file *filep) +{ + return file_close_detached(filep); +} +#endif + +#endif /* CONFIG_ROUTE_IPv4_FILEROUTE || CONFIG_ROUTE_IPv6_FILEROUTE */ diff --git a/net/route/net_foreach_fileroute.c b/net/route/net_foreach_fileroute.c new file mode 100644 index 00000000000..ecacff2097e --- /dev/null +++ b/net/route/net_foreach_fileroute.c @@ -0,0 +1,213 @@ +/**************************************************************************** + * net/route/net_foreach_fileroute.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include +#include + +#include + +#include "route/fileroute.h" +#include "route/route.h" + +#if defined(CONFIG_ROUTE_IPv4_FILEROUTE) || defined(CONFIG_ROUTE_IPv6_FILEROUTE) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_foreachroute_ipv4 and net_foreachroute_ipv6 + * + * Description: + * Traverse the routing table + * + * Parameters: + * handler - Will be called for each route in the routing table. + * arg - An arbitrary value that will be passed tot he handler. + * + * Returned Value: + * Zero (OK) returned if the entire table was search. A negated errno + * value will be returned in the event of a failure. Handlers may also + * terminate the search early with any non-zero, non-negative value. + * + ****************************************************************************/ + +#ifdef CONFIG_ROUTE_IPv4_FILEROUTE +int net_foreachroute_ipv4(route_handler_t handler, FAR void *arg) +{ + struct net_route_ipv4_s route; + struct file fshandle; + ssize_t nread; + int ret = 0; + + /* Open the IPv4 routing table for read-only access */ + + ret = net_openroute_ipv4(O_RDONLY, &fshandle); + if (ret < 0) + { + /* Special case: the routing table has not yet been created. This is + * not an error. We will just want to return successful completion of + * the traversal. + */ + + if (ret == -ENOENT) + { + /* The routing table does not exit.. return successful completion */ + + ninfo("The IPv4 routing table file does not exist\n"); + return OK; + } + + /* Some other error occurred. */ + + nerr("ERROR: Could not open IPv4 routing table: %d\n", ret); + return ret; + } + + /* Read each entry from the routing table */ + + for (; ; ) + { + nread = net_readroute_ipv4(&fshandle, &route); + if (nread < 0) + { + /* File read error */ + + nerr("ERROR: net_readroute_ipv4() failed: %ld\n", (long)nread); + ret = (int)nread; + break; + } + else if (nread == 0) + { + /* End of file */ + + ret = OK; + break; + } + + /* Call the handler. */ + + ret = handler(&route, arg); + if (ret != OK) + { + /* Terminate early if the handler returns any non-zero value. */ + + break; + } + } + + (void)net_closeroute_ipv4(&fshandle); + return ret; +} +#endif + +#ifdef CONFIG_ROUTE_IPv6_FILEROUTE +int net_foreachroute_ipv6(route_handler_ipv6_t handler, FAR void *arg) +{ + struct net_route_ipv6_s route; + struct file fshandle; + ssize_t nread; + int ret = 0; + + /* Open the IPv6 routing table for read-only access */ + + ret = net_openroute_ipv6(O_RDONLY, &fshandle); + if (ret < 0) + { + /* Special case: the routing table has not yet been created. This is + * not an error. We will just want to return successful completion of + * the traversal. + */ + + if (ret == -ENOENT) + { + /* The routing table does not exit.. return successful completion */ + + ninfo("The IPv6 routing table file does not exist\n"); + return OK; + } + + /* Some other error occurred. */ + + nerr("ERROR: Could not open IPv6 routing table: %d\n", ret); + return ret; + } + + /* Read each entry from the routing table */ + + for (; ; ) + { + nread = net_readroute_ipv6(&fshandle, &route); + if (nread < 0) + { + /* File read error */ + + nerr("ERROR: net_readroute_ipv6() failed: %ld\n", (long)nread); + ret = (int)nread; + break; + } + else if (nread == 0) + { + /* End of file */ + + ret = OK; + break; + } + + /* Call the handler. */ + + ret = handler(&route, arg); + if (ret != OK) + { + /* Terminate early if the handler returns any non-zero value. */ + + break; + } + } + + (void)net_closeroute_ipv6(&fshandle); + return ret; +} +#endif + +#endif /* CONFIG_ROUTE_IPv4_FILEROUTE || CONFIG_ROUTE_IPv6_FILEROUTE */ diff --git a/net/route/net_foreach_ramroute.c b/net/route/net_foreach_ramroute.c index c28eeddbfdd..9d34481d63c 100644 --- a/net/route/net_foreach_ramroute.c +++ b/net/route/net_foreach_ramroute.c @@ -66,7 +66,9 @@ * arg - An arbitrary value that will be passed tot he handler. * * Returned Value: - * 0 if in use; 1 if avaialble and the new entry was added + * Zero (OK) returned if the entire table was search. A negated errno + * value will be returned in the event of a failure. Handlers may also + * terminate the search early with any non-zero, non-negative value. * ****************************************************************************/ diff --git a/net/route/net_foreach_romroute.c b/net/route/net_foreach_romroute.c index f5aebaa3c31..7f8001aaa43 100644 --- a/net/route/net_foreach_romroute.c +++ b/net/route/net_foreach_romroute.c @@ -41,8 +41,6 @@ #include -#include - #include "route/romroute.h" #include "route/route.h" @@ -63,7 +61,9 @@ * arg - An arbitrary value that will be passed tot he handler. * * Returned Value: - * 0 if in use; 1 if avaialble and the new entry was added + * Zero (OK) returned if the entire table was search. A negated errno + * value will be returned in the event of a failure. Handlers may also + * terminate the search early with any non-zero, non-negative value. * ****************************************************************************/ diff --git a/net/route/net_initroute.c b/net/route/net_initroute.c index 03c84ba3a4c..8fa1d7d43ca 100644 --- a/net/route/net_initroute.c +++ b/net/route/net_initroute.c @@ -40,6 +40,7 @@ #include #include "route/ramroute.h" +#include "route/fileroute.h" #include "route/route.h" #ifdef CONFIG_NET_ROUTE @@ -67,6 +68,10 @@ void net_init_route(void) #if defined(CONFIG_ROUTE_IPv4_RAMROUTE) || defined(CONFIG_ROUTE_IPv6_RAMROUTE) net_init_ramroute(); #endif + +#if defined(CONFIG_ROUTE_IPv4_FILEROUTE) || defined(CONFIG_ROUTE_IPv6_FILEROUTE) + net_init_fileroute(); +#endif } #endif /* CONFIG_NET_ROUTE */ diff --git a/net/route/ramroute.h b/net/route/ramroute.h index 37d177536c1..ad02ad1ff12 100644 --- a/net/route/ramroute.h +++ b/net/route/ramroute.h @@ -129,7 +129,7 @@ extern struct net_route_ipv6_queue_s g_ipv6_routes; #endif /**************************************************************************** - * Public Functions + * Public Function Prototypes ****************************************************************************/ /**************************************************************************** diff --git a/net/route/romroute.h b/net/route/romroute.h index c1c1955a208..a775d452f6f 100644 --- a/net/route/romroute.h +++ b/net/route/romroute.h @@ -69,7 +69,7 @@ extern const unsigned int g_ipv6_nroutes; #endif /**************************************************************************** - * Public Functions + * Public Function Prototypes ****************************************************************************/ #endif /* CONFIG_ROUTE_IPv4_ROMROUTE || CONFIG_ROUTE_IPv6_ROMROUTE */ diff --git a/net/route/route.h b/net/route/route.h index 410693f46e7..619898055b3 100644 --- a/net/route/route.h +++ b/net/route/route.h @@ -266,9 +266,13 @@ void netdev_ipv6_router(FAR struct net_driver_s *dev, * Traverse the routing table * * Parameters: + * handler - Will be called for each route in the routing table. + * arg - An arbitrary value that will be passed tot he handler. * * Returned Value: - * OK on success; Negated errno on failure. + * Zero (OK) returned if the entire table was search. A negated errno + * value will be returned in the event of a failure. Handlers may also + * terminate the search early with any non-zero, non-negative value. * ****************************************************************************/