From a627561c8f8b6cd72ffe45ed8574411929342040 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 2 Oct 2020 15:43:24 -0600 Subject: [PATCH] apps/fsutils/ipcfg: Add support for IPv6 --- examples/ipcfg/Kconfig | 5 +- examples/ipcfg/ipcfg_main.c | 442 ++++++++++++++++++- fsutils/ipcfg/Kconfig | 27 +- fsutils/ipcfg/Makefile | 7 +- fsutils/ipcfg/ipcfg.c | 564 +++++------------------- fsutils/ipcfg/ipcfg.h | 238 +++++++++++ fsutils/ipcfg/ipcfg_binary.c | 568 ++++++++++++++++++++++++ fsutils/ipcfg/ipcfg_text.c | 805 +++++++++++++++++++++++++++++++++++ include/fsutils/ipcfg.h | 9 +- 9 files changed, 2166 insertions(+), 499 deletions(-) create mode 100644 fsutils/ipcfg/ipcfg.h create mode 100644 fsutils/ipcfg/ipcfg_binary.c create mode 100644 fsutils/ipcfg/ipcfg_text.c diff --git a/examples/ipcfg/Kconfig b/examples/ipcfg/Kconfig index 3fbbfdd86..6de98753c 100644 --- a/examples/ipcfg/Kconfig +++ b/examples/ipcfg/Kconfig @@ -4,11 +4,12 @@ # config EXAMPLES_IPCFG - tristate "IPv4 Configuration file example" + tristate "IP Configuration file example" default n select FS_TMPFS + depends on FSUTILS_IPCFG ---help--- - Enable the IPv4 Configuration file example + Enable the IP Configuration file example if EXAMPLES_IPCFG diff --git a/examples/ipcfg/ipcfg_main.c b/examples/ipcfg/ipcfg_main.c index c899b2df9..bf42b4367 100644 --- a/examples/ipcfg/ipcfg_main.c +++ b/examples/ipcfg/ipcfg_main.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include @@ -46,12 +48,17 @@ #define DEVICE1 "eth0" #define DEVICE2 "eth1" +#define PATH1 CONFIG_IPCFG_PATH "/ipcfg-" DEVICE1 +#define PATH2 CONFIG_IPCFG_PATH "/ipcfg-" DEVICE2 #define IPv4PROTO_MAX IPv4PROTO_FALLBACK +#define IPv6PROTO_MAX IPv6PROTO_FALLBACK +#define IOBUFFERSIZE 1024 /**************************************************************************** * Private Data ****************************************************************************/ +#ifdef CONFIG_NET_IPv4 static const char *g_ipv4proto_name[] = { "none", /* IPv4PROTO_NONE */ @@ -59,22 +66,216 @@ static const char *g_ipv4proto_name[] = "dhcp", /* IPv4PROTO_DHCP */ "fallback" /* IPv4PROTO_FALLBACK */ }; +#endif + +#ifdef CONFIG_NET_IPv6 +static const char *g_ipv6proto_name[] = +{ + "none", /* IPv6PROTO_NONE */ + "static", /* IPv6PROTO_STATIC */ + "autoconf", /* IPv6PROTO_AUTOCONF */ + "fallback" /* IPv6PROTO_FALLBACK */ +}; + +static const uint16_t g_ipv6_ipaddr[8] = +{ + HTONS(0xfc00), + HTONS(0x0000), + HTONS(0x0000), + HTONS(0x0000), + HTONS(0x0000), + HTONS(0x0000), + HTONS(0x0000), + HTONS(0x0002), +}; + +static const uint16_t g_ipv6_netmask[8] = +{ + HTONS(0xffff), + HTONS(0xffff), + HTONS(0xffff), + HTONS(0xffff), + HTONS(0xffff), + HTONS(0xffff), + HTONS(0x0000), + HTONS(0x0000), +}; + +static const uint16_t g_ipv6_router[8] = +{ + HTONS(0xfc00), + HTONS(0x0000), + HTONS(0x0000), + HTONS(0x0000), + HTONS(0x0000), + HTONS(0x0000), + HTONS(0x0000), + HTONS(0x0001), +}; +#endif /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** - * Name: ipcfg_dump_addr + * Name: ipcfg_nibble + * + * Description: + * Convert a binary nibble to a hexadecimal character. + * ****************************************************************************/ -static void ipcfg_dump_addr(FAR const char *variable, in_addr_t address) +#ifdef CONFIG_IPCFG_BINARY +static char ipcfg_nibble(unsigned char nibble) { - if (address == 0) + if (nibble < 10) { - printf("%s[UNSPECIFIED]\n", variable); + return '0' + nibble; } else + { + return 'a' + nibble - 10; + } +} +#endif + +/**************************************************************************** + * Name: ipcfg_dump_file + * + * Description: + * Dump the contents of a file to stdout. + * + * Input Paratemets: + * filepath - The full path to the file to be dumped + * + * Returned Value: + * Zero (OK) on success; -1 (ERROR) on failure. + * + ****************************************************************************/ + +int ipcfg_dump_file(FAR const char *filepath) +{ + FAR char *buffer; +#ifdef CONFIG_IPCFG_BINARY + int nbytes = 0; +#endif + int fd; + int ret = OK; + + /* Open the file for reading */ + + fd = open(filepath, O_RDONLY); + if (fd < 0) + { + ret = -errno; + fprintf(stderr, "ERROR: Failed to open %s: %d\n", filepath, ret); + return ret; + } + + buffer = (FAR char *)malloc(IOBUFFERSIZE); + if (buffer == NULL) + { + ret = -ENOMEM; + fprintf(stderr, "ERROR: Failed to allocate buffer\n"); + goto errout_with_fd; + } + + /* And just dump it byte for byte into stdout */ + + for (; ; ) + { + ssize_t nbytesread = read(fd, buffer, IOBUFFERSIZE); + + /* Check for read errors */ + + if (nbytesread < 0) + { + ret = -errno; + fprintf(stderr, "ERROR: Read failed: %d\n", ret); + goto errout_with_buffer; + } + + /* Check for data successfully read */ + + else if (nbytesread > 0) + { +#ifndef CONFIG_IPCFG_BINARY + int nbyteswritten = 0; + + while (nbyteswritten < nbytesread) + { + ssize_t n = write(1, buffer + nbyteswritten, + nbytesread - nbyteswritten); + if (n < 0) + { + ret = -errno; + fprintf(stderr, "ERROR: Write failed: %d\n", ret); + goto errout_with_buffer; + } + else + { + nbyteswritten += n; + } + } +#else + int i; + + for (i = 0; i < nbytesread; i++) + { + uint8_t byte = buffer[i]; + + if (nbytes == 0) + { + printf(" "); + } + + putchar(ipcfg_nibble(byte >> 4)); + putchar(ipcfg_nibble(byte & 0x0f)); + + if (++nbytes == 16) + { + putchar(' '); + } + + if (nbytes == 32) + { + putchar('\n'); + nbytes = 0; + } + } +#endif + } + + /* Otherwise, it is the end of file */ + + else + { +#ifdef CONFIG_IPCFG_BINARY + putchar('\n'); +#endif + break; + } + } + + /* Close the input file and return the result */ + +errout_with_buffer: + free(buffer); + +errout_with_fd: + close(fd); + return ret; +} + +/**************************************************************************** + * Name: ipcfg_dump_ipv4addr + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv4 +static void ipcfg_dump_ipv4addr(FAR const char *variable, in_addr_t address) +{ + if (address != 0) { struct in_addr saddr = { @@ -84,12 +285,65 @@ static void ipcfg_dump_addr(FAR const char *variable, in_addr_t address) printf("%s%s\n", variable, inet_ntoa(saddr)); } } +#endif /**************************************************************************** - * Name: ipcfg_dump_config + * Name: ipcfg_check_ipv6addr ****************************************************************************/ -static int ipcfg_dump_config(FAR const char *netdev) +#ifdef CONFIG_NET_IPv6 +static int ipcfg_check_ipv6addr(FAR const struct in6_addr *address) +{ + int i; + + for (i = 0; i < 4; i++) + { + if (address->s6_addr32[i] != 0) + { + return OK; + } + } + + return -ENXIO; +} +#endif + +/**************************************************************************** + * Name: ipcfg_dump_ipv6addr + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +static void ipcfg_dump_ipv6addr(FAR const char *variable, + FAR const struct in6_addr *address) +{ + int ret; + + ret = ipcfg_check_ipv6addr(address); + if (ret == OK) + { + char converted[INET6_ADDRSTRLEN]; + + /* Convert the address to ASCII text */ + + if (inet_ntop(AF_INET6, address, converted, INET6_ADDRSTRLEN) == NULL) + { + ret = -errno; + fprintf(stderr, "ERROR: inet_ntop() failed: %d\n", ret); + } + else + { + printf("%s%s\n", variable, converted); + } + } +} +#endif + +/**************************************************************************** + * Name: ipcfg_dump_ipv4config + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv4 +static int ipcfg_dump_ipv4config(FAR const char *netdev) { struct ipv4cfg_s ipv4cfg; int ret; @@ -103,35 +357,112 @@ static int ipcfg_dump_config(FAR const char *netdev) /* Dump the content in human readable form */ - printf("%s:\n", netdev); - if (ipv4cfg.proto > IPv4PROTO_MAX) { - printf("BOOTPROTO: %d [INVALID]\n", ipv4cfg.proto); + printf("\n IPv4BOOTPROTO: %d [INVALID]\n", ipv4cfg.proto); + return -EINVAL; } else { - printf("BOOTPROTO: %s\n", g_ipv4proto_name[ipv4cfg.proto]); + printf("\n IPv4BOOTPROTO: %s\n", g_ipv4proto_name[ipv4cfg.proto]); } - ipcfg_dump_addr("IPADDR: ", ipv4cfg.ipaddr); - ipcfg_dump_addr("NETMASK: ", ipv4cfg.netmask); - ipcfg_dump_addr("ROUTER: ", ipv4cfg.router); - ipcfg_dump_addr("DNS: ", ipv4cfg.dnsaddr); + if (ipv4cfg.proto == IPv4PROTO_STATIC || + ipv4cfg.proto == IPv4PROTO_FALLBACK) + { + ipcfg_dump_ipv4addr(" IPv4IPADDR: ", ipv4cfg.ipaddr); + ipcfg_dump_ipv4addr(" IPv4NETMASK: ", ipv4cfg.netmask); + ipcfg_dump_ipv4addr(" IPv4ROUTER: ", ipv4cfg.router); + ipcfg_dump_ipv4addr(" IPv4DNS: ", ipv4cfg.dnsaddr); + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: ipcfg_dump_ipv6config + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +static int ipcfg_dump_ipv6config(FAR const char *netdev) +{ + struct ipv6cfg_s ipv6cfg; + int ret; + + ret = ipcfg_read(netdev, (FAR struct ipcfg_s *)&ipv6cfg, AF_INET6); + if (ret < 0) + { + fprintf(stderr, "ERROR: ipcfg_read() failed: %d\n", ret); + return ret; + } + + /* Dump the content in human readable form */ + + if (ipv6cfg.proto > IPv6PROTO_MAX) + { + printf("\n IPv6BOOTPROTO: %d [INVALID]\n", ipv6cfg.proto); + return -EINVAL; + } + else + { + printf("\n IPv6BOOTPROTO: %s\n", g_ipv6proto_name[ipv6cfg.proto]); + } + + if (ipv6cfg.proto == IPv6PROTO_STATIC || + ipv6cfg.proto == IPv6PROTO_FALLBACK) + { + ipcfg_dump_ipv6addr(" IPv6IPADDR: ", &ipv6cfg.ipaddr); + ipcfg_dump_ipv6addr(" IPv6NETMASK: ", &ipv6cfg.netmask); + ipcfg_dump_ipv6addr(" IPv6ROUTER: ", &ipv6cfg.router); + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: ipcfg_dump_config + ****************************************************************************/ + +static int ipcfg_dump_config(FAR const char *netdev) +{ + int ret; + + printf("\n%s:\n", netdev); + +#ifdef CONFIG_NET_IPv4 + ret = ipcfg_dump_ipv4config(netdev); + if (ret < 0) + { + return ret; + } +#endif + +#ifdef CONFIG_NET_IPv6 + ret = ipcfg_dump_ipv6config(netdev); + if (ret < 0) + { + return ret; + } +#endif return OK; } /**************************************************************************** - * Name: ipcfg_write_config + * Name: ipcfg_write_ipv4 ****************************************************************************/ -static int ipcfg_write_config(FAR const char *netdev) +#ifdef CONFIG_NET_IPv4 +static int ipcfg_write_ipv4(FAR const char *netdev) { struct ipv4cfg_s ipv4cfg; int ret; - ipv4cfg.proto = IPv4PROTO_DHCP; + memset(&ipv4cfg, 0, sizeof(struct ipv4cfg_s)); + + ipv4cfg.proto = IPv4PROTO_FALLBACK; ipv4cfg.ipaddr = HTONL(0x0a000002); ipv4cfg.netmask = HTONL(0xffffff00); ipv4cfg.router = HTONL(0x0a000001); @@ -145,6 +476,73 @@ static int ipcfg_write_config(FAR const char *netdev) return ret; } +#endif + +/**************************************************************************** + * Name: ipcfg_write_ipv6 + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +static int ipcfg_write_ipv6(FAR const char *netdev) +{ + struct ipv6cfg_s ipv6cfg; + int ret; + + memset(&ipv6cfg, 0, sizeof(struct ipv6cfg_s)); + + ipv6cfg.proto = IPv6PROTO_FALLBACK; + + memcpy(ipv6cfg.ipaddr.s6_addr16, g_ipv6_ipaddr, + sizeof(struct in6_addr)); + memcpy(ipv6cfg.netmask.s6_addr16, g_ipv6_netmask, + sizeof(struct in6_addr)); + memcpy(ipv6cfg.router.s6_addr16, g_ipv6_router, + sizeof(struct in6_addr)); + + ret = ipcfg_write(netdev, (FAR struct ipcfg_s *)&ipv6cfg, AF_INET6); + if (ret < 0) + { + fprintf(stderr, "ERROR: ipcfg_write() ipcfg_write: %d\n", ret); + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: ipcfg_write_config + ****************************************************************************/ + +static int ipcfg_write_config(FAR const char *netdev, FAR const char *path) +{ + int ret; + + /* Write IPv6 first which might cause re-organization of file */ + +#ifdef CONFIG_NET_IPv6 + ret = ipcfg_write_ipv6(netdev); + if (ret < 0) + { + return ret; + } + + printf("\n %s after IPv6 Update:\n", path); + ipcfg_dump_file(path); +#endif + +#ifdef CONFIG_NET_IPv4 + ret = ipcfg_write_ipv4(netdev); + if (ret < 0) + { + return ret; + } + + printf("\n %s after IPv4 Update:\n", path); + ipcfg_dump_file(path); +#endif + + return OK; +} /**************************************************************************** * Public Functions @@ -166,14 +564,14 @@ int main(int argc, FAR char *argv[]) if (ret < 0) { int errcode = errno; - fprintf(stderr, "ERROR: Failed to open " CONFIG_IPCFG_PATH "\n: %d", + fprintf(stderr, "ERROR: Failed to mount " CONFIG_IPCFG_PATH "\n: %d", errcode); return EXIT_FAILURE; } /* Dump files. These should all fail. */ - printf("\n1. Dump before creating configuration files\n\n"); + printf("\n1. Dump before creating configuration files\n"); ipcfg_dump_config(DEVICE1); ipcfg_dump_config(DEVICE2); @@ -181,12 +579,12 @@ int main(int argc, FAR char *argv[]) /* Create files */ printf("\n2. Create configuration files\n\n"); - ipcfg_write_config(DEVICE1); - ipcfg_write_config(DEVICE2); + ipcfg_write_config(DEVICE1, PATH1); + ipcfg_write_config(DEVICE2, PATH2); /* Dump the files again */ - printf("\n3. Dump after creating configuration files\n\n"); + printf("\n3. Dump after creating configuration files\n"); ipcfg_dump_config(DEVICE1); ipcfg_dump_config(DEVICE2); #endif diff --git a/fsutils/ipcfg/Kconfig b/fsutils/ipcfg/Kconfig index 9979f6a3e..77696a1e1 100644 --- a/fsutils/ipcfg/Kconfig +++ b/fsutils/ipcfg/Kconfig @@ -4,41 +4,38 @@ # config FSUTILS_IPCFG - bool "IPv4 Configuration File Support" + bool "IP Configuration File Support" default n - depends on NET_IPv4 + depends on NET_IPv4 || NET_IPv6 ---help--- - Enables support for an IPv4 configuration file that holds IP + Enables support for an IP configuration file that holds IP address and/or DHCP configuration information for a specific network device - There is no dependency on IPv4 networking support so this - configuration may be used in testing without a network. - if FSUTILS_IPCFG config IPCFG_WRITABLE - bool "Writable IPv4 Configuration" + bool "Writable IP Configuration" default y ---help--- - Can be used to disable writing to the IPv4 Configuration file. This - would be necessary if, for example, the IPv4 Configuration file were + Can be used to disable writing to the IP Configuration file. This + would be necessary if, for example, the IP Configuration file were provided on a read-only file system. config IPCFG_BINARY - bool "Binary IPv4 Configuration File" + bool "Binary IP Configuration File" default n ---help--- - By default, the IPv4 configuration file is an ASCII human readable + By default, the IP configuration file is an ASCII human readable file with = pairs. A Binary interface may be used for more constrained media such as EEPROM. config IPCFG_PATH - string "IPv4 Configuration File Directory" + string "IP Configuration File Directory" default "/etc/sysconfig/network-scripts" ---help--- Specifies the full path to the directory or mountpoint that holds - the IPv4 Configuration files. Each individual configuration file + the IP Configuration files. Each individual configuration file within this directory will have names like ipcfg-eth0. If CONFIG_IPCFG_CHARDEV is select, this setting is interpreted @@ -62,10 +59,10 @@ config IPCFG_OFFSET default 0 depends on IPCFG_CHARDEV ---help--- - Seek to this offset before reading or writing the IPv4 Configuration. + Seek to this offset before reading or writing the IP Configuration. This is only support for the character driver device. This permits some formatting of, say, EEPROM, so that multiple, different - configurations can be maintained at differnt offsets into the IPv4 + configurations can be maintained at differnt offsets into the IP Configuration File. endif # FSUTILS_IPCFG diff --git a/fsutils/ipcfg/Makefile b/fsutils/ipcfg/Makefile index de6dcb259..7b63d6e02 100644 --- a/fsutils/ipcfg/Makefile +++ b/fsutils/ipcfg/Makefile @@ -20,10 +20,15 @@ include $(APPDIR)/Make.defs -# IPv4 Configuration file access library +# IP Configuration file access library ifeq ($(CONFIG_FSUTILS_IPCFG),y) CSRCS += ipcfg.c +ifeq ($(CONFIG_IPCFG_BINARY),y) +CSRCS += ipcfg_binary.c +else +CSRCS += ipcfg_text.c +endif endif include $(APPDIR)/Application.mk diff --git a/fsutils/ipcfg/ipcfg.c b/fsutils/ipcfg/ipcfg.c index 34e62e374..d1f00b3f4 100644 --- a/fsutils/ipcfg/ipcfg.c +++ b/fsutils/ipcfg/ipcfg.c @@ -26,49 +26,10 @@ #include #include -#include -#include -#include - -#include -#include +#include #include "fsutils/ipcfg.h" - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -#define MAX_LINESIZE 80 -#define MAX_IPv4PROTO IPv4PROTO_FALLBACK - -/* Values for the record type field */ - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -/* IP Configuration record header. */ - -struct ipcfg_header_s -{ - uint8_t next; /* Offset to the next IP configuration record */ - sa_family_t type; /* Must be AF_INET */ -}; - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -#if defined(CONFIG_IPCFG_WRITABLE) && !defined(CONFIG_IPCFG_BINARY) -static const char *g_ipv4proto_name[] = -{ - "none", /* IPv4PROTO_NONE */ - "static", /* IPv4PROTO_STATIC */ - "dhcp", /* IPv4PROTO_DHCP */ - "fallback" /* IPv4PROTO_FALLBACK */ -}; -#endif +#include "ipcfg.h" /**************************************************************************** * Private Functions @@ -107,8 +68,7 @@ static inline FAR char *ipcfg_allocpath(FAR const char *netdev) { /* Assume that asprintf failed to allocate memory */ - fprintf(stderr, "ERROR: Failed to create path to ipcfg file: %d\n", - ret); + ferr("ERROR: Failed to create path to ipcfg file: %d\n", ret); return NULL; } @@ -126,201 +86,6 @@ static inline FAR char *ipcfg_allocpath(FAR const char *netdev) #endif } -/**************************************************************************** - * Name: ipcfg_open (for ASCII mode) - * - * Description: - * Form the complete path to the ipcfg file and open it. - * - * Input Parameters: - * netdev - The network device. For examplel "eth0" - * stream - Location to return the opened stream - * mode - File fopen mode - * - * Returned Value: - * Zero is returned on success; a negated errno value is returned on any - * failure. - * - ****************************************************************************/ - -#ifndef CONFIG_IPCFG_BINARY -static int ipcfg_open(FAR const char *netdev, FAR FILE **stream, - FAR const char *mode) -{ - FAR char *path; - int ret; - - /* Create the full path to the ipcfg file for the network device */ - - path = ipcfg_allocpath(netdev); - if (path == NULL) - { - /* Assume failure to allocate memory */ - - fprintf(stderr, "ERROR: Failed to create path to ipcfg file\n"); - return -ENOMEM; - } - - /* Now open the file */ - - *stream = fopen(path, mode); - ret = OK; - - if (*stream == NULL) - { - ret = -errno; - fprintf(stderr, "ERROR: Failed to open %s: %d\n", path, ret); - } - - free(path); - return ret; -} -#endif - -/**************************************************************************** - * Name: ipcfg_open (for binary mode) - * - * Description: - * Form the complete path to the ipcfg file and open it. - * - * Input Parameters: - * netdev - The network device. For examplel "eth0" - * oflags - File open flags - * mode - File creation mode - * - * Returned Value: - * The open file descriptor is returned on success; a negated errno value - * is returned on any failure. - * - ****************************************************************************/ - -#ifdef CONFIG_IPCFG_BINARY -static int ipcfg_open(FAR const char *netdev, int oflags, mode_t mode) -{ - FAR char *path; - int fd; - int ret; - - /* Create the full path to the ipcfg file for the network device */ - - path = ipcfg_allocpath(netdev); - if (path == NULL) - { - /* Assume failure to allocate memory */ - - fprintf(stderr, "ERROR: Failed to create path to ipcfg file\n"); - return -ENOMEM; - } - - /* Now open the file */ - - fd = open(path, oflags, mode); - if (fd < 0) - { - ret = -errno; - fprintf(stderr, "ERROR: Failed to open %s: %d\n", path, ret); - goto errout_with_path; - } - -#if defined(CONFIG_IPCFG_OFFSET) && CONFIG_IPCFG_OFFSET > 0 - /* If the binary file is accessed on a character device as a binary - * file, then there is also an option to seek to a location on the - * media before reading or writing the file. - */ - - ret = lseek(fd, CONFIG_IPCFG_OFFSET, SEEK_SET); - if (ret < 0) - { - ret = -errno; - close(fd); - fprintf(stderr, "ERROR: Failed to seek to $ld: %d\n", - (long)CONFIG_IPCFG_OFFSET, ret); - goto errout_with_path; - } - -#endif - ret = fd; - -errout_with_path: - free(path); - return ret; -} -#endif - -/**************************************************************************** - * Name: ipcfg_trim - * - * Description: - * Skip over any whitespace. - * - * Input Parameters: - * line - Pointer to line buffer - * index - Current index into the line buffer - * - * Returned Value: - * New value of index. - * - ****************************************************************************/ - -#ifndef CONFIG_IPCFG_BINARY -static int ipcfg_trim(FAR char *line, int index) -{ - int ret; - while (line[index] != '\0' && isspace(line[index])) - { - index++; - } - - ret = index; - while (line[index] != '\0') - { - if (!isprint(line[index])) - { - line[index] = '\0'; - break; - } - - index++; - } - - return ret; -} -#endif - -/**************************************************************************** - * Name: ipcfg_putaddr - * - * Description: - * Write a =
value pair to the stream. - * - * Input Parameters: - * stream - The output stream - * variable - The variable namespace - * address - The IP address to write - * - * Returned Value: - * None. - * - ****************************************************************************/ - -#if defined(CONFIG_IPCFG_WRITABLE) && !defined(CONFIG_IPCFG_BINARY) -static void ipcfg_putaddr(FAR FILE *stream, FAR const char *variable, - in_addr_t address) -{ - /* REVISIT: inet_ntoa() is not thread safe. */ - - if (address != 0) - { - struct in_addr saddr = - { - address - }; - - fprintf(stream, "%s=%s\n", variable, inet_ntoa(saddr)); - } -} -#endif - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -349,182 +114,84 @@ static void ipcfg_putaddr(FAR FILE *stream, FAR const char *variable, int ipcfg_read(FAR const char *netdev, FAR void *ipcfg, sa_family_t af) { #ifdef CONFIG_IPCFG_BINARY - FAR struct ipv4cfg_s *ipv4cfg = (FAR struct ipv4cfg_s *)ipcfg; - struct ipcfg_header_s hdr; - ssize_t nread; - int fd; + FAR char *path; int ret; - DEBUGASSERT(netdev != NULL && ipv4cfg != NULL && af == AF_INET); + DEBUGASSERT(netdev != NULL && ipcfg != NULL); - /* Open the file */ + /* Create the full path to the ipcfg file for the network device */ - fd = ipcfg_open(netdev, O_RDONLY, 0666); - if (fd < 0) + path = ipcfg_allocpath(netdev); + if (path == NULL) { - return fd; + /* Assume failure to allocate memory */ + + ferr("ERROR: Failed to create path to ipcfg file\n"); + return -ENOMEM; } - /* Read the header */ - - nread = read(fd, &hdr, sizeof(struct ipcfg_header_s)); - if (nread < 0) +#ifdef CONFIG_NET_IPv4 + if (af == AF_INET) { - ret = -errno; - fprintf(stderr, "ERROR: Failed to read file: %d\n", ret); - goto errout_with_fd; - } - else if (nread != sizeof(struct ipcfg_header_s)) - { - ret = -EIO; - fprintf(stderr, "ERROR: Bad read size: %ld\n", (long)nread); - goto errout_with_fd; - } - - /* Verify the header. Only a single IPv4 header is anticipated */ - - if (hdr.next != 0 || hdr.type != AF_INET) - { - ret = -EINVAL; - fprintf(stderr, "ERROR: Bad header: {%u,%u}\n", - hdr.next, hdr.type); - goto errout_with_fd; - } - - /* Read the file content */ - - nread = read(fd, ipv4cfg, sizeof(struct ipv4cfg_s)); - if (nread < 0) - { - ret = -errno; - fprintf(stderr, "ERROR: Failed to read file: %d\n", ret); - } - else if (nread != sizeof(struct ipv4cfg_s)) - { - ret = -EIO; - fprintf(stderr, "ERROR: Bad read size: %ld\n", (long)nread); + ret = ipcfg_read_binary_ipv4(path, (FAR struct ipv4cfg_s *)ipcfg); } else +#endif +#ifdef CONFIG_NET_IPv6 + if (af == AF_INET6) { - ret = OK; + ret = ipcfg_read_binary_ipv6(path, (FAR struct ipv6cfg_s *)ipcfg); + } + else +#endif + { + ferr("ERROR: Unsupported address family: %d\n", af); + ret = -EAFNOSUPPORT; } -errout_with_fd: - close(fd); + free(path); return ret; #else - FAR struct ipv4cfg_s *ipv4cfg = (FAR struct ipv4cfg_s *)ipcfg; - FAR FILE *stream; - char line[MAX_LINESIZE]; - int index; + FAR char *path; int ret; - DEBUGASSERT(netdev != NULL && ipv4cfg != NULL && af == AF_INET); + DEBUGASSERT(netdev != NULL && ipcfg != NULL); - /* Open the file */ + /* Create the full path to the ipcfg file for the network device */ - ret = ipcfg_open(netdev, &stream, "r"); - if (ret < 0) + path = ipcfg_allocpath(netdev); + if (path == NULL) { - return ret; + /* Assume failure to allocate memory */ + + ferr("ERROR: Failed to create path to ipcfg file\n"); + return -ENOMEM; } - /* Process each line in the file */ - - memset(ipv4cfg, 0, sizeof(FAR struct ipv4cfg_s)); - - while (fgets(line, MAX_LINESIZE, stream) != NULL) +#ifdef CONFIG_NET_IPv4 + if (af == AF_INET) { - /* Skip any leading whitespace */ - - index = ipcfg_trim(line, 0); - - /* Check for a blank line or a comment */ - - if (line[index] != '\0' && line[index] != '#') - { - FAR char *variable = &line[index]; - FAR char *value; - - /* Expect = pair */ - - value = strchr(variable, '='); - if (value == NULL) - { - fprintf(stderr, "ERROR: Skipping malformed line in file: %s\n", - line); - continue; - } - - /* NUL-terminate the variable string */ - - *value++ = '\0'; - - /* Process the variable assignment */ - - if (strcmp(variable, "DEVICE") == 0) - { - /* Just assure that it matches the filename */ - - if (strcmp(value, netdev) != 0) - { - fprintf(stderr, "ERROR: Bad device in file: %s=%s\n", - variable, value); - } - } - else if (strcmp(variable, "IPv4PROTO") == 0) - { - if (strcmp(value, "none") == 0) - { - ipv4cfg->proto = IPv4PROTO_NONE; - } - else if (strcmp(value, "static") == 0) - { - ipv4cfg->proto = IPv4PROTO_STATIC; - } - else if (strcmp(value, "dhcp") == 0) - { - ipv4cfg->proto = IPv4PROTO_DHCP; - } - else if (strcmp(value, "fallback") == 0) - { - ipv4cfg->proto = IPv4PROTO_FALLBACK; - } - else - { - fprintf(stderr, "ERROR: Unrecognized IPv4PROTO: %s=%s\n", - variable, value); - } - } - else if (strcmp(variable, "IPv4IPADDR") == 0) - { - ipv4cfg->ipaddr = inet_addr(value); - } - else if (strcmp(variable, "IPv4NETMASK") == 0) - { - ipv4cfg->netmask = inet_addr(value); - } - else if (strcmp(variable, "IPv4ROUTER") == 0) - { - ipv4cfg->router = inet_addr(value); - } - else if (strcmp(variable, "IPv4DNS") == 0) - { - ipv4cfg->dnsaddr = inet_addr(value); - } - else - { - fprintf(stderr, "ERROR: Unrecognized variable: %s=%s\n", - variable, value); - } - } + ret = ipcfg_read_text_ipv4(path, netdev, + (FAR struct ipv4cfg_s *)ipcfg); + } + else +#endif +#ifdef CONFIG_NET_IPv6 + if (af == AF_INET6) + { + ret = ipcfg_read_text_ipv6(path, netdev, + (FAR struct ipv6cfg_s *)ipcfg); + } + else +#endif + { + ferr("ERROR: Unsupported address family: %d\n", af); + ret = -EAFNOSUPPORT; } - /* Close the file and return */ - - fclose(stream); - return OK; + free(path); + return ret; #endif } @@ -552,99 +219,86 @@ int ipcfg_write(FAR const char *netdev, FAR const void *ipcfg, sa_family_t af) { #ifdef CONFIG_IPCFG_BINARY - FAR struct ipv4cfg_s *ipv4cfg = (FAR struct ipv4cfg_s *)ipcfg; - struct ipcfg_header_s hdr; - ssize_t nwritten; - int fd; + FAR char *path; int ret; - DEBUGASSERT(netdev != NULL && ipv4cfg != NULL && af == AF_INET); + DEBUGASSERT(netdev != NULL && ipcfg != NULL); - /* Open the file */ + /* Create the full path to the ipcfg file for the network device */ - fd = ipcfg_open(netdev, O_WRONLY | O_TRUNC | O_CREAT, 0666); - if (fd < 0) + path = ipcfg_allocpath(netdev); + if (path == NULL) { - return fd; + /* Assume failure to allocate memory */ + + ferr("ERROR: Failed to create path to ipcfg file\n"); + return -ENOMEM; } - /* Write the file header */ - - hdr.next = 0; - hdr.type = AF_INET; - - nwritten = write(fd, &hdr, sizeof(struct ipcfg_header_s)); - if (nwritten < 0) +#ifdef CONFIG_NET_IPv4 + if (af == AF_INET) { - ret = -errno; - fprintf(stderr, "ERROR: Failed to write to file: %d\n", ret); - goto errout_with_fd; - } - else if (nwritten != sizeof(struct ipcfg_header_s)) - { - ret = -EIO; - fprintf(stderr, "ERROR: Bad write size: %ld\n", (long)nwritten); - goto errout_with_fd; - } - - /* Write the file content */ - - nwritten = write(fd, ipv4cfg, sizeof(struct ipv4cfg_s)); - if (nwritten < 0) - { - ret = -errno; - fprintf(stderr, "ERROR: Failed to write file: %d\n", ret); - } - else if (nwritten != sizeof(struct ipv4cfg_s)) - { - ret = -EIO; - fprintf(stderr, "ERROR: Bad write size: %ld\n", (long)nwritten); + ret = ipcfg_write_binary_ipv4(path, + (FAR const struct ipv4cfg_s *)ipcfg); } else +#endif +#ifdef CONFIG_NET_IPv6 + if (af == AF_INET6) { - ret = OK; + ret = ipcfg_write_binary_ipv6(path, + (FAR const struct ipv6cfg_s *)ipcfg); + } + else +#endif + { + ferr("ERROR: Unsupported address family: %d\n", af); + ret = -EAFNOSUPPORT; } -errout_with_fd: - close(fd); + free(path); return ret; #else - FAR struct ipv4cfg_s *ipv4cfg = (FAR struct ipv4cfg_s *)ipcfg; - FAR FILE *stream; + FAR char *path; int ret; - DEBUGASSERT(netdev != NULL && ipv4cfg != NULL && af == AF_INET); + DEBUGASSERT(netdev != NULL && ipcfg != NULL); - /* Open the file */ + /* Create the full path to the ipcfg file for the network device */ - ret = ipcfg_open(netdev, &stream, "w"); - if (ret < 0) + path = ipcfg_allocpath(netdev); + if (path == NULL) { - return ret; + /* Assume failure to allocate memory */ + + ferr("ERROR: Failed to create path to ipcfg file\n"); + return -ENOMEM; } - /* Format and write the file */ - - if ((unsigned)ipv4cfg->proto > MAX_IPv4PROTO) +#ifdef CONFIG_NET_IPv4 + if (af == AF_INET) { - fprintf(stderr, "ERROR: Unrecognized IPv4PROTO value: %d\n", - ipv4cfg->proto); - return -EINVAL; + ret = ipcfg_write_text_ipv4(path, netdev, + (FAR const struct ipv4cfg_s *)ipcfg); + } + else +#endif +#ifdef CONFIG_NET_IPv6 + if (af == AF_INET6) + { + ret = ipcfg_write_text_ipv6(path, netdev, + (FAR const struct ipv6cfg_s *)ipcfg); + } + else +#endif + { + ferr("ERROR: Unsupported address family: %d\n", af); + ret = -EAFNOSUPPORT; } - fprintf(stream, "DEVICE=%s\n", netdev); - fprintf(stream, "IPv4PROTO=%s\n", g_ipv4proto_name[ipv4cfg->proto]); - - ipcfg_putaddr(stream, "IPv4IPADDR", ipv4cfg->ipaddr); - ipcfg_putaddr(stream, "IPv4NETMASK", ipv4cfg->netmask); - ipcfg_putaddr(stream, "IPv4ROUTER", ipv4cfg->router); - ipcfg_putaddr(stream, "IPv4DNS", ipv4cfg->dnsaddr); - - /* Close the file and return */ - - fclose(stream); - return OK; + free(path); + return ret; #endif } #endif diff --git a/fsutils/ipcfg/ipcfg.h b/fsutils/ipcfg/ipcfg.h new file mode 100644 index 000000000..a2c1a63c0 --- /dev/null +++ b/fsutils/ipcfg/ipcfg.h @@ -0,0 +1,238 @@ +/**************************************************************************** + * apps/fsutils/ipcfg/ipcfg.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __APPS_FSUTILS_IPCFG_IPCFG_H +#define __APPS_FSUTILS_IPCFG_IPCFG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include "fsutils/ipcfg.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MAX_LINESIZE 80 +#define MAX_IPv4PROTO IPv4PROTO_FALLBACK +#define MAX_IPv6PROTO IPv6PROTO_FALLBACK + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* IP Configuration record header. */ + +struct ipcfg_header_s +{ + uint8_t next; /* Offset to the next IP configuration record */ + sa_family_t type; /* Either AF_INET or AF_INET6 */ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: ipcfg_read_binary_ipv4 + * + * Description: + * Read IPv4 configuration from a binary IP Configuration file. + * + * Input Parameters: + * path - The full path to the IP configuration file + * ipv4cfg - Location to read IPv4 configration to + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#if defined(CONFIG_IPCFG_BINARY) && defined(CONFIG_NET_IPv4) +int ipcfg_read_binary_ipv4(FAR const char *path, + FAR struct ipv4cfg_s *ipv4cfg); +#endif + +/**************************************************************************** + * Name: ipcfg_read_binary_ipv6 + * + * Description: + * Read IPv6 configuration from a binary IP Configuration file. + * + * Input Parameters: + * path - The full path to the IP configuration file + * ipv6cfg - Location to read IPv6 configration to + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#if defined(CONFIG_IPCFG_BINARY) && defined(CONFIG_NET_IPv6) +int ipcfg_read_binary_ipv6(FAR const char *path, + FAR struct ipv6cfg_s *ipv6cfg); +#endif + +/**************************************************************************** + * Name: ipcfg_write_binary_ipv4 + * + * Description: + * Write the IPv4 configuration to a binary IP Configuration file. + * + * Input Parameters: + * path - The full path to the IP configuration file + * ipv4cfg - The IPv4 configration to write + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#if defined(CONFIG_IPCFG_WRITABLE) && defined(CONFIG_IPCFG_BINARY) && \ + defined(CONFIG_NET_IPv4) +int ipcfg_write_binary_ipv4(FAR const char *path, + FAR const struct ipv4cfg_s *ipv4cfg); +#endif + +/**************************************************************************** + * Name: ipcfg_write_binary_ipv6 + * + * Description: + * Write the IPv6 configuration to a binary IP Configuration file. + * + * Input Parameters: + * path - The full path to the IP configuration file + * ipv6cfg - The IPv6 configration to write + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#if defined(CONFIG_IPCFG_WRITABLE) && defined(CONFIG_IPCFG_BINARY) && \ + defined(CONFIG_NET_IPv6) +int ipcfg_write_binary_ipv6(FAR const char *path, + FAR const struct ipv6cfg_s *ipv6cfg); +#endif + +/**************************************************************************** + * Name: ipcfg_read_text_ipv4 + * + * Description: + * Read IPv4 configuration from a human-readable, text IP Configuration + * file. + * + * Input Parameters: + * path - The full path to the IP configuration file + * netdev - Network device name string + * ipv4cfg - Location to read IPv4 configration to + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv4 +int ipcfg_read_text_ipv4(FAR const char *path, FAR const char *netdev, + FAR struct ipv4cfg_s *ipv4cfg); +#endif + +/**************************************************************************** + * Name: ipcfg_read_text_ipv6 + * + * Description: + * Read IPv6 configuration from a human-readable, text IP Configuration + * file. + * + * Input Parameters: + * path - The full path to the IP configuration file + * netdev - Network device name string + * ipv6cfg - Location to read IPv6 configration to + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +int ipcfg_read_text_ipv6(FAR const char *path, FAR const char *netdev, + FAR struct ipv6cfg_s *ipv6cfg); +#endif + +/**************************************************************************** + * Name: ipcfg_write_text_ipv4 + * + * Description: + * Write the IPv4 configuration to a human-readable, text IP Configuration + * file. + * + * Input Parameters: + * path - The full path to the IP configuration file + * netdev - Network device name string + * ipv4cfg - The IPv4 configration to write + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#if defined(CONFIG_IPCFG_WRITABLE) && defined(CONFIG_NET_IPv4) +int ipcfg_write_text_ipv4(FAR const char *path, FAR const char *netdev, + FAR const struct ipv4cfg_s *ipv4cfg); +#endif + +/**************************************************************************** + * Name: ipcfg_write_text_ipv6 + * + * Description: + * Write the IPv6 configuration to a human-readable, text IP Configuration + * file. + * + * Input Parameters: + * path - The full path to the IP configuration file + * netdev - Network device name string + * ipv6cfg - The IPv6 configration to write + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#if defined(CONFIG_IPCFG_WRITABLE) && defined(CONFIG_NET_IPv6) +int ipcfg_write_text_ipv6(FAR const char *path, FAR const char *netdev, + FAR const struct ipv6cfg_s *ipv6cfg); +#endif + +#endif /* __APPS_FSUTILS_IPCFG_IPCFG_H */ diff --git a/fsutils/ipcfg/ipcfg_binary.c b/fsutils/ipcfg/ipcfg_binary.c new file mode 100644 index 000000000..9af338624 --- /dev/null +++ b/fsutils/ipcfg/ipcfg_binary.c @@ -0,0 +1,568 @@ +/**************************************************************************** + * apps/fsutils/ipcfg/ipcfg_binary.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "fsutils/ipcfg.h" +#include "ipcfg.h" + +#ifdef CONFIG_IPCFG_BINARY + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ipcfg_open (for binary mode) + * + * Description: + * Form the complete path to the ipcfg file and open it. + * + * Input Parameters: + * path - The full path to the IP configuration file + * oflags - File open flags + * mode - File creation mode + * + * Returned Value: + * The open file descriptor is returned on success; a negated errno value + * is returned on any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_IPCFG_BINARY +static int ipcfg_open(FAR const char *path, int oflags, mode_t mode) +{ + int fd; + int ret; + + /* Now open the file */ + + fd = open(path, oflags, mode); + if (fd < 0) + { + ret = -errno; + if (ret != -ENOENT) + { + ferr("ERROR: Failed to open %s: %d\n", path, ret); + } + + return ret; + } + +#if defined(CONFIG_IPCFG_OFFSET) && CONFIG_IPCFG_OFFSET > 0 + /* If the binary file is accessed on a character device as a binary + * file, then there is also an option to seek to a location on the + * media before reading or writing the file. + */ + + ret = lseek(fd, CONFIG_IPCFG_OFFSET, SEEK_SET); + if (ret < 0) + { + ret = -errno; + ferr("ERROR: Failed to seek to $ld: %d\n", + (long)CONFIG_IPCFG_OFFSET, ret); + + close(fd); + return ret; + } + +#endif + + return fd; +} +#endif + +/**************************************************************************** + * Name: ipcfg_read_binary + * + * Description: + * Read from a binary IP Configuration file. + * + * Input Parameters: + * fd - File descriptor of the open file to read from + * buffer - Location to read from + * nbytes - Number of bytes to read + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +static int ipcfg_read_binary(int fd, FAR void *buffer, size_t nbytes) +{ + ssize_t nread; + int ret; + + /* Read from the file */ + + nread = read(fd, buffer, nbytes); + if (nread < 0) + { + ret = -errno; + ferr("ERROR: Failed to read from file: %d\n", ret); + } + else if (nread != nbytes) + { + ret = -EIO; + ferr("ERROR: Bad read size: %ld\n", (long)nread); + } + else + { + ret = OK; + } + + return ret; +} + +/**************************************************************************** + * Name: ipcfg_write_binary + * + * Description: + * Write to a binary IP Configuration file. + * + * Input Parameters: + * fd - File descriptor of the open file to write to + * buffer - Location to write to + * nbytes - Number of bytes to wrtie + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#ifdef CONFIG_IPCFG_WRITABLE +static int ipcfg_write_binary(int fd, FAR const void *buffer, size_t nbytes) +{ + ssize_t nwritten; + int ret; + + /* Read from the file */ + + nwritten = write(fd, buffer, nbytes); + if (nwritten < 0) + { + ret = -errno; + ferr("ERROR: Failed to write to file: %d\n", ret); + } + else if (nwritten != nbytes) + { + ret = -EIO; + ferr("ERROR: Bad write size: %ld\n", (long)nwritten); + } + else + { + ret = OK; + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: ipcfg_find_binary + * + * Description: + * Read the location of IPv4 data in a binary IP Configuration file. + * + * Input Parameters: + * fd - File descriptor of the open file to read from + * af - Identifies the address family whose IP configuration is + * requested. May be either AF_INET or AF_INET6. + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +static int ipcfg_find_binary(int fd, sa_family_t af) +{ + struct ipcfg_header_s hdr; + off_t pos; + int ret; + + for (; ; ) + { + /* Read the header (careful.. could be uninitialized in the case of a + * character driver). + */ + + ret = ipcfg_read_binary(fd, &hdr, sizeof(struct ipcfg_header_s)); + if (ret < 0) + { + /* Return on any read error */ + + return (int)ret; + } + else if (hdr.type == af) + { + return OK; + } + else if (hdr.type != AF_INET && hdr.type != AF_INET6) + { + return -EINVAL; + } + else if (hdr.next == 0) + { + ferr("ERROR: IP configuration not found\n"); + return -ENOENT; + } + + /* Skip to the next IP configuration record */ + + pos = lseek(fd, hdr.next, SEEK_CUR); + if (pos < 0) + { + ret = -errno; + ferr("ERROR: lseek failed: %d\n", ret); + return ret; + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ipcfg_read_binary_ipv4 + * + * Description: + * Read IPv4 configuration from a binary IP Configuration file. + * + * Input Parameters: + * path - The full path to the IP configuration file + * ipv4cfg - Location to read IPv4 configration to + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv4 +int ipcfg_read_binary_ipv4(FAR const char *path, + FAR struct ipv4cfg_s *ipv4cfg) +{ + int fd; + int ret; + + DEBUGASSERT(path != NULL && ipv4cfg != NULL); + + /* Open the file for reading */ + + fd = ipcfg_open(path, O_RDONLY, 0666); + if (fd < 0) + { + return fd; + } + + /* Find the IPv4 binary in the IP configuration file */ + + ret = ipcfg_find_binary(fd, AF_INET); + if (ret < 0) + { + goto errout_with_fd; + } + + /* Read the IPv4 Configuration */ + + ret = ipcfg_read_binary(fd, ipv4cfg, sizeof(struct ipv4cfg_s)); + +errout_with_fd: + close(fd); + return ret; +} +#endif + +/**************************************************************************** + * Name: ipcfg_read_binary_ipv6 + * + * Description: + * Read IPv6 configuration from a binary IP Configuration file. + * + * Input Parameters: + * path - The full path to the IP configuration file + * ipv6cfg - Location to read IPv6 configration to + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +int ipcfg_read_binary_ipv6(FAR const char *path, + FAR struct ipv6cfg_s *ipv6cfg) +{ + int fd; + int ret; + + DEBUGASSERT(fd >= 0 && ipv6cfg != NULL); + + /* Open the file for reading */ + + fd = ipcfg_open(path, O_RDONLY, 0666); + if (fd < 0) + { + return fd; + } + + /* Find the IPv6 binary in the IP configuration file */ + + ret = ipcfg_find_binary(fd, AF_INET6); + if (ret < 0) + { + goto errout_with_fd; + } + + /* Read the IPv6 Configuration */ + + ret = ipcfg_read_binary(fd, ipv6cfg, sizeof(struct ipv6cfg_s)); + +errout_with_fd: + close(fd); + return ret; +} +#endif + +/**************************************************************************** + * Name: ipcfg_write_binary_ipv4 + * + * Description: + * Write the IPv4 configuration to a binary IP Configuration file. + * + * Input Parameters: + * path - The full path to the IP configuration file + * ipv4cfg - The IPv4 configration to write + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#if defined(CONFIG_IPCFG_WRITABLE) && defined(CONFIG_NET_IPv4) +int ipcfg_write_binary_ipv4(FAR const char *path, + FAR const struct ipv4cfg_s *ipv4cfg) +{ +#ifdef CONFIG_NET_IPv6 + struct ipv6cfg_s ipv6cfg; +#endif + struct ipcfg_header_s hdr; + bool ipv6 = false; + int fd; + int ret; + + DEBUGASSERT(fd >= 0 && ipv4cfg != NULL); + +#ifdef CONFIG_NET_IPv6 + /* Read any IPv6 data in the file */ + + ret = ipcfg_read_binary_ipv6(path, &ipv6cfg); + if (ret < 0) + { + /* -ENOENT is not an error. It simply means that there is no IPv6 + * configuration in the file. + */ + + if (ret != -ENOENT) + { + return ret; + } + } + else + { + ipv6 = true; + } +#endif + + /* Open the file for writing (truncates) */ + + fd = ipcfg_open(path, O_WRONLY | O_TRUNC | O_CREAT, 0666); + if (fd < 0) + { + return fd; + } + + /* Write the IPv4 file header */ + + hdr.next = ipv6 ? sizeof(struct ipv4cfg_s) : 0; + hdr.type = AF_INET; + + ret = ipcfg_write_binary(fd, &hdr, sizeof(struct ipcfg_header_s)); + if (ret < 0) + { + goto errout_with_fd; + } + + /* Write the IPv4 configuration */ + + ret = ipcfg_write_binary(fd, ipv4cfg, sizeof(struct ipv4cfg_s)); + if (ret < 0) + { + goto errout_with_fd; + } + +#ifdef CONFIG_NET_IPv6 + /* Followed by any IPv6 data in the file */ + + if (ipv6) + { + /* Write the IPv6 header */ + + hdr.next = 0; + hdr.type = AF_INET6; + + ret = ipcfg_write_binary(fd, &hdr, sizeof(struct ipcfg_header_s)); + if (ret >= 0) + { + /* Write the IPv6 configuration */ + + ret = ipcfg_write_binary(fd, &ipv6cfg, sizeof(struct ipv6cfg_s)); + } + } +#endif + +errout_with_fd: + close(fd); + return ret; +} +#endif + +/**************************************************************************** + * Name: ipcfg_write_binary_ipv6 + * + * Description: + * Write the IPv6 configuration to a binary IP Configuration file. + * + * Input Parameters: + * path - The full path to the IP configuration file + * ipv6cfg - The IPv6 configration to write + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#if defined(CONFIG_IPCFG_WRITABLE) && defined(CONFIG_NET_IPv6) +int ipcfg_write_binary_ipv6(FAR const char *path, + FAR const struct ipv6cfg_s *ipv6cfg) +{ +#ifdef CONFIG_NET_IPv4 + struct ipv4cfg_s ipv4cfg; + bool ipv4 = false; +#endif + struct ipcfg_header_s hdr; + int fd; + int ret; + + DEBUGASSERT(path != NULL && ipv6cfg != NULL); + +#ifdef CONFIG_NET_IPv4 + /* Read any IPv4 data in the file */ + + ret = ipcfg_read_binary_ipv4(path, &ipv4cfg); + if (ret < 0) + { + /* -ENOENT is not an error. It simply means that there is no IPv4 + * configuration in the file. + */ + + if (ret != -ENOENT) + { + return ret; + } + } + else + { + ipv4 = true; + } +#endif + + /* Open the file for writing (truncates) */ + + fd = ipcfg_open(path, O_WRONLY | O_TRUNC | O_CREAT, 0666); + if (fd < 0) + { + return fd; + } + +#ifdef CONFIG_NET_IPv4 + if (ipv4) + { + /* Write the IPv4 header */ + + hdr.next = sizeof(struct ipv4cfg_s); + hdr.type = AF_INET; + + ret = ipcfg_write_binary(fd, &hdr, sizeof(struct ipcfg_header_s)); + if (ret < 0) + { + goto errout_with_fd; + } + + /* Write the IPv4 configuration. This is really unnecessary in most + * cases since the IPv4 data should already be in place. + */ + + ret = ipcfg_write_binary(fd, &ipv4cfg, sizeof(struct ipv4cfg_s)); + if (ret < 0) + { + goto errout_with_fd; + } + } +#endif + + /* Write the IPv6 file header */ + + hdr.next = 0; + hdr.type = AF_INET6; + + ret = ipcfg_write_binary(fd, &hdr, sizeof(struct ipcfg_header_s)); + if (ret >= 0) + { + /* Write the IPv6 configuration */ + + ret = ipcfg_write_binary(fd, ipv6cfg, sizeof(struct ipv6cfg_s)); + } + +#ifdef CONFIG_NET_IPv4 +errout_with_fd: +#endif + close(fd); + return ret; +} +#endif + +#endif /* CONFIG_IPCFG_BINARY */ diff --git a/fsutils/ipcfg/ipcfg_text.c b/fsutils/ipcfg/ipcfg_text.c new file mode 100644 index 000000000..ca0944e6c --- /dev/null +++ b/fsutils/ipcfg/ipcfg_text.c @@ -0,0 +1,805 @@ +/**************************************************************************** + * apps/fsutils/ipcfg/ipcfg_text.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "fsutils/ipcfg.h" +#include "ipcfg.h" + +#ifndef CONFIG_IPCFG_BINARY + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#if defined(CONFIG_IPCFG_WRITABLE) && defined(CONFIG_NET_IPv4) +static const char *g_ipv4proto_name[] = +{ + "none", /* IPv4PROTO_NONE */ + "static", /* IPv4PROTO_STATIC */ + "dhcp", /* IPv4PROTO_DHCP */ + "fallback" /* IPv4PROTO_FALLBACK */ +}; +#endif + +#if defined(CONFIG_IPCFG_WRITABLE) && defined(CONFIG_NET_IPv6) +static const char *g_ipv6proto_name[] = +{ + "none", /* IPv6PROTO_NONE */ + "static", /* IPv6PROTO_STATIC */ + "autoconf", /* IPv6PROTO_AUTOCONF */ + "fallback" /* IPv6PROTO_FALLBACK */ +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ipcfg_trim + * + * Description: + * Skip over any whitespace. + * + * Input Parameters: + * line - Pointer to line buffer + * index - Current index into the line buffer + * + * Returned Value: + * New value of index. + * + ****************************************************************************/ + +#ifndef CONFIG_IPCFG_BINARY +static int ipcfg_trim(FAR char *line, int index) +{ + int ret; + while (line[index] != '\0' && isspace(line[index])) + { + index++; + } + + ret = index; + while (line[index] != '\0') + { + if (!isprint(line[index])) + { + line[index] = '\0'; + break; + } + + index++; + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: ipcfg_put_ipv4addr + * + * Description: + * Write a =
value pair to the stream. + * + * Input Parameters: + * stream - The output stream + * variable - The variable namespace + * address - The IP address to write + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#if defined(CONFIG_IPCFG_WRITABLE) && defined(CONFIG_NET_IPv4) +static int ipcfg_put_ipv4addr(FAR FILE *stream, FAR const char *variable, + in_addr_t address) +{ + if (address != 0) + { + struct in_addr saddr = + { + address + }; + + char converted[INET_ADDRSTRLEN]; + + /* Convert the address to ASCII text */ + + if (inet_ntop(AF_INET, &saddr, converted, INET_ADDRSTRLEN) == NULL) + { + int ret = -errno; + ferr("ERROR: inet_ntop() failed: %d\n", ret); + return ret; + } + + fprintf(stream, "%s=%s\n", variable, converted); + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: ipcfg_check_ipv6addr + * + * Description: + * Check for a valid IPv6 address, i.e., not all zeroes. + * + * Input Parameters: + * address - A pointer to the address to check. + * + * Returned value: + * Zero (OK) is returned if the address is non-zero. -ENXIO is returned if + * the address is zero. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +static int ipcfg_check_ipv6addr(FAR const struct in6_addr *address) +{ + int i; + + for (i = 0; i < 4; i++) + { + if (address->s6_addr32[i] != 0) + { + return OK; + } + } + + return -ENXIO; +} +#endif + +/**************************************************************************** + * Name: ipcfg_put_ipv6addr + * + * Description: + * Write a =
value pair to the stream. + * + * Input Parameters: + * stream - The output stream + * variable - The variable namespace + * address - The IP address to write + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#if defined(CONFIG_IPCFG_WRITABLE) && defined(CONFIG_NET_IPv6) +static int ipcfg_put_ipv6addr(FAR FILE *stream, FAR const char *variable, + FAR const struct in6_addr *address) +{ + /* If the address is all zero, then omit it */ + + if (ipcfg_check_ipv6addr(address) == OK) + { + char converted[INET6_ADDRSTRLEN]; + + /* Convert the address to ASCII text */ + + if (inet_ntop(AF_INET6, address, converted, INET6_ADDRSTRLEN) == NULL) + { + int ret = -errno; + ferr("ERROR: inet_ntop() failed: %d\n", ret); + return ret; + } + + fprintf(stream, "%s=%s\n", variable, converted); + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: ipcfg_write_ipv4 + * + * Description: + * Write the IPv4 configuration to a human-readable, text IP Configuration + * file. + * + * Input Parameters: + * stream - Stream of the open file to write to + * ipv4cfg - The IPv4 configration to write + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#if defined(CONFIG_IPCFG_WRITABLE) && defined(CONFIG_NET_IPv4) +static int ipcfg_write_ipv4(FAR FILE *stream, + FAR const struct ipv4cfg_s *ipv4cfg) +{ + /* Format and write the file */ + + if ((unsigned)ipv4cfg->proto > MAX_IPv4PROTO) + { + ferr("ERROR: Unrecognized IPv4PROTO value: %d\n", ipv4cfg->proto); + return -EINVAL; + } + + fprintf(stream, "IPv4PROTO=%s\n", g_ipv4proto_name[ipv4cfg->proto]); + + ipcfg_put_ipv4addr(stream, "IPv4IPADDR", ipv4cfg->ipaddr); + ipcfg_put_ipv4addr(stream, "IPv4NETMASK", ipv4cfg->netmask); + ipcfg_put_ipv4addr(stream, "IPv4ROUTER", ipv4cfg->router); + ipcfg_put_ipv4addr(stream, "IPv4DNS", ipv4cfg->dnsaddr); + + return OK; +} +#endif + +/**************************************************************************** + * Name: ipcfg_write_ipv6 + * + * Description: + * Write the IPv6 configuration to a human-readable, text IP Configuration + * file. + * + * Input Parameters: + * stream - Stream of the open file to write to + * ipv6cfg - The IPv6 configration to write + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#if defined(CONFIG_IPCFG_WRITABLE) && defined(CONFIG_NET_IPv6) +static int ipcfg_write_ipv6(FAR FILE *stream, + FAR const struct ipv6cfg_s *ipv6cfg) +{ + /* Format and write the file */ + + if ((unsigned)ipv6cfg->proto > MAX_IPv6PROTO) + { + ferr("ERROR: Unrecognized IPv6PROTO value: %d\n", ipv6cfg->proto); + return -EINVAL; + } + + fprintf(stream, "IPv6PROTO=%s\n", g_ipv6proto_name[ipv6cfg->proto]); + + ipcfg_put_ipv6addr(stream, "IPv6IPADDR", &ipv6cfg->ipaddr); + ipcfg_put_ipv6addr(stream, "IPv6NETMASK", &ipv6cfg->netmask); + ipcfg_put_ipv6addr(stream, "IPv6ROUTER", &ipv6cfg->router); + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ipcfg_read_text_ipv4 + * + * Description: + * Read IPv4 configuration from a human-readable, text IP Configuration + * file. + * + * Input Parameters: + * path - The full path to the IP configuration file + * netdev - Network device name string + * ipv4cfg - Location to read IPv4 configration to + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv4 +int ipcfg_read_text_ipv4(FAR const char *path, FAR const char *netdev, + FAR struct ipv4cfg_s *ipv4cfg) +{ + char line[MAX_LINESIZE]; + FAR FILE *stream; + int index; + int ret = -ENOENT; + + DEBUGASSERT(stream != NULL && ipv4cfg != NULL); + + /* Open the file for reading */ + + stream = fopen(path, "r"); + if (stream == NULL) + { + ret = -errno; + if (ret != -ENOENT) + { + ferr("ERROR: Failed to open %s: %d\n", path, ret); + } + + return ret; + } + + /* Process each line in the file */ + + memset(ipv4cfg, 0, sizeof(FAR struct ipv4cfg_s)); + + while (fgets(line, MAX_LINESIZE, stream) != NULL) + { + /* Skip any leading whitespace */ + + index = ipcfg_trim(line, 0); + + /* Check for a blank line or a comment */ + + if (line[index] != '\0' && line[index] != '#') + { + FAR char *variable = &line[index]; + FAR char *value; + + /* Expect = pair */ + + value = strchr(variable, '='); + if (value == NULL) + { + ferr("ERROR: Skipping malformed line in file: %s\n", line); + continue; + } + + /* NUL-terminate the variable string */ + + *value++ = '\0'; + + /* Process the variable assignment */ + + if (strcmp(variable, "DEVICE") == 0) + { + /* Just assure that it matches the filename */ + + if (strcmp(value, netdev) != 0) + { + ferr("ERROR: Bad device in file: %s=%s\n", + variable, value); + } + } + else if (strcmp(variable, "IPv4PROTO") == 0) + { + if (strcmp(value, "none") == 0) + { + ipv4cfg->proto = IPv4PROTO_NONE; + } + else if (strcmp(value, "static") == 0) + { + ipv4cfg->proto = IPv4PROTO_STATIC; + } + else if (strcmp(value, "dhcp") == 0) + { + ipv4cfg->proto = IPv4PROTO_DHCP; + } + else if (strcmp(value, "fallback") == 0) + { + ipv4cfg->proto = IPv4PROTO_FALLBACK; + } + else + { + ferr("ERROR: Unrecognized IPv4PROTO: %s=%s\n", + variable, value); + } + + /* Assume IPv4 settings are present if the IPv4BOOTPROTO + * setting is encountered. + */ + + ret = OK; + } + else if (strcmp(variable, "IPv4IPADDR") == 0) + { + ipv4cfg->ipaddr = inet_addr(value); + } + else if (strcmp(variable, "IPv4NETMASK") == 0) + { + ipv4cfg->netmask = inet_addr(value); + } + else if (strcmp(variable, "IPv4ROUTER") == 0) + { + ipv4cfg->router = inet_addr(value); + } + else if (strcmp(variable, "IPv4DNS") == 0) + { + ipv4cfg->dnsaddr = inet_addr(value); + } + + /* Anything other than some IPv6 settings would be an error. + * This is a sloppy check because it does not detect invalid + * names variables that begin with "IPv6". + */ + + else if (strncmp(variable, "IPv6", 4) != 0) + { + ferr("ERROR: Unrecognized variable: %s=%s\n", variable, value); + } + } + } + + /* Close the file and return */ + + fclose(stream); + return ret; +} +#endif + +/**************************************************************************** + * Name: ipcfg_read_text_ipv6 + * + * Description: + * Read IPv6 configuration from a human-readable, text IP Configuration + * file. + * + * Input Parameters: + * path - The full path to the IP configuration file + * netdev - Network device name string + * ipv6cfg - Location to read IPv6 configration to + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +int ipcfg_read_text_ipv6(FAR const char *path, FAR const char *netdev, + FAR struct ipv6cfg_s *ipv6cfg) +{ + char line[MAX_LINESIZE]; + FAR FILE *stream; + bool found = false; + int index; + int ret; + + DEBUGASSERT(path != NULL && netdev != NULL && ipv6cfg != NULL); + + /* Open the file for reading */ + + stream = fopen(path, "r"); + if (stream == NULL) + { + ret = -errno; + if (ret != -ENOENT) + { + ferr("ERROR: Failed to open %s: %d\n", path, ret); + } + + return ret; + } + + /* Process each line in the file */ + + memset(ipv6cfg, 0, sizeof(FAR struct ipv6cfg_s)); + + while (fgets(line, MAX_LINESIZE, stream) != NULL) + { + /* Skip any leading whitespace */ + + index = ipcfg_trim(line, 0); + + /* Check for a blank line or a comment */ + + if (line[index] != '\0' && line[index] != '#') + { + FAR char *variable = &line[index]; + FAR char *value; + + /* Expect = pair */ + + value = strchr(variable, '='); + if (value == NULL) + { + ferr("ERROR: Skipping malformed line in file: %s\n", line); + continue; + } + + /* NUL-terminate the variable string */ + + *value++ = '\0'; + + /* Process the variable assignment */ + + if (strcmp(variable, "DEVICE") == 0) + { + /* Just assure that it matches the filename */ + + if (strcmp(value, netdev) != 0) + { + ferr("ERROR: Bad device in file: %s=%s\n", + variable, value); + } + } + else if (strcmp(variable, "IPv6PROTO") == 0) + { + if (strcmp(value, "none") == 0) + { + ipv6cfg->proto = IPv6PROTO_NONE; + } + else if (strcmp(value, "static") == 0) + { + ipv6cfg->proto = IPv6PROTO_STATIC; + } + else if (strcmp(value, "autoconf") == 0) + { + ipv6cfg->proto = IPv6PROTO_AUTOCONF; + } + else if (strcmp(value, "fallback") == 0) + { + ipv6cfg->proto = IPv6PROTO_FALLBACK; + } + else + { + ferr("ERROR: Unrecognized IPv6PROTO: %s=%s\n", + variable, value); + } + + /* Assume IPv4 settings are present if the IPv6BOOTPROTO + * setting is encountered. + */ + + found = true; + } + else if (strcmp(variable, "IPv6IPADDR") == 0) + { + ret = inet_pton(AF_INET6, value, &ipv6cfg->ipaddr); + if (ret < 0) + { + ret = -errno; + ferr("ERROR: inet_pton() failed: %d\n", ret); + return ret; + } + } + else if (strcmp(variable, "IPv6NETMASK") == 0) + { + ret = inet_pton(AF_INET6, value, &ipv6cfg->netmask); + if (ret < 0) + { + ret = -errno; + ferr("ERROR: inet_pton() failed: %d\n", ret); + return ret; + } + } + else if (strcmp(variable, "IPv6ROUTER") == 0) + { + ret = inet_pton(AF_INET6, value, &ipv6cfg->router); + if (ret < 0) + { + ret = -errno; + ferr("ERROR: inet_pton() failed: %d\n", ret); + return ret; + } + } + + /* Anything other than some IPv4 settings would be an error. + * This is a sloppy check because it does not detect invalid + * names variables that begin with "IPv4". + */ + + else if (strncmp(variable, "IPv4", 4) != 0) + { + ferr("ERROR: Unrecognized variable: %s=%s\n", variable, value); + } + } + } + + /* Close the file and return */ + + fclose(stream); + return found ? OK : -ENOENT; +} +#endif + +/**************************************************************************** + * Name: ipcfg_write_text_ipv4 + * + * Description: + * Write the IPv4 configuration to a human-readable, text IP Configuration + * file. + * + * Input Parameters: + * path - The full path to the IP configuration file + * netdev - Network device name string + * ipv4cfg - The IPv4 configration to write + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#if defined(CONFIG_IPCFG_WRITABLE) && defined(CONFIG_NET_IPv4) +int ipcfg_write_text_ipv4(FAR const char *path, FAR const char *netdev, + FAR const struct ipv4cfg_s *ipv4cfg) +{ +#ifdef CONFIG_NET_IPv6 + struct ipv6cfg_s ipv6cfg; + bool ipv6 = false; +#endif + FAR FILE *stream; + int ret; + + DEBUGASSERT(stream != NULL && ipv4cfg != NULL); + +#ifdef CONFIG_NET_IPv6 + /* Read any IPv6 data in the file */ + + ret = ipcfg_read_text_ipv6(path, netdev, &ipv6cfg); + if (ret < 0) + { + /* -ENOENT is not an error. It simply means that there is no IPv6 + * configuration in the file. + */ + + if (ret != -ENOENT) + { + return ret; + } + } + else + { + ipv6 = true; + } +#endif + + /* Open the file for writing (truncates) */ + + stream = fopen(path, "w"); + if (stream == NULL) + { + ret = -errno; + ferr("ERROR: Failed to open %s: %d\n", path, ret); + return ret; + } + + /* Save the device name */ + + fprintf(stream, "DEVICE=%s\n", netdev); + + /* Write the IPv4 configuration */ + + ret = ipcfg_write_ipv4(stream, ipv4cfg); + if (ret < 0) + { + return ret; + } + +#ifdef CONFIG_NET_IPv6 + /* Followed by any IPv6 data in the file */ + + if (ipv6) + { + ret = ipcfg_write_ipv6(stream, &ipv6cfg); + } +#endif + + fclose(stream); + return ret; +} +#endif + +/**************************************************************************** + * Name: ipcfg_write_text_ipv6 + * + * Description: + * Write the IPv6 configuration to a binary IP Configuration file. + * + * Input Parameters: + * path - The full path to the IP configuration file + * netdev - Network device name string + * ipv6cfg - The IPv6 configration to write + * + * Returned Value: + * Zero is returned on success; a negated errno value is returned on any + * failure. + * + ****************************************************************************/ + +#if defined(CONFIG_IPCFG_WRITABLE) && defined(CONFIG_NET_IPv6) +int ipcfg_write_text_ipv6(FAR const char *path, FAR const char *netdev, + FAR const struct ipv6cfg_s *ipv6cfg) +{ +#ifdef CONFIG_NET_IPv4 + struct ipv4cfg_s ipv4cfg; + bool ipv4 = false; +#endif + FAR FILE *stream; + int ret; + + DEBUGASSERT(netdev != NULL && ipv6cfg != NULL); + +#ifdef CONFIG_NET_IPv4 + /* Read any IPv4 data in the file */ + + ret = ipcfg_read_text_ipv4(path, netdev, &ipv4cfg); + if (ret < 0) + { + /* -ENOENT is not an error. It simply means that there is no IPv4 + * configuration in the file. + */ + + if (ret != -ENOENT) + { + return ret; + } + } + else + { + ipv4 = true; + } +#endif + + /* Open the file for writing (truncates) */ + + stream = fopen(path, "w"); + if (stream == NULL) + { + ret = -errno; + ferr("ERROR: Failed to open %s: %d\n", path, ret); + return ret; + } + + /* Save the device name */ + + fprintf(stream, "DEVICE=%s\n", netdev); + +#ifdef CONFIG_NET_IPv4 + if (ipv4) + { + /* Write the IPv4 configuration. This is really unnecessary in most + * cases since the IPv4 data should already be in place. + */ + + ret = ipcfg_write_ipv4(stream, &ipv4cfg); + if (ret < 0) + { + return ret; + } + } +#endif + + /* Write the IPv6 configuration */ + + ret = ipcfg_write_ipv6(stream, ipv6cfg); + fclose(stream); + return ret; +} +#endif + +#endif /* !CONFIG_IPCFG_BINARY */ diff --git a/include/fsutils/ipcfg.h b/include/fsutils/ipcfg.h index 63eaa2c40..3b411785a 100644 --- a/include/fsutils/ipcfg.h +++ b/include/fsutils/ipcfg.h @@ -123,10 +123,10 @@ struct ipv4cfg_s enum ipv6cfg_bootproto_e { - BOOTPROTO_NONE = 0, /* No protocol assigned */ - BOOTPROTO_STATIC = 1, /* Use static IP */ - BOOTPROTO_AUTOCONF = 2, /* Use ICMPv6 auto-configuration */ - BOOTPROTO_FALLBACK = 3 /* Use auto-configuration with fall back static IP */ + IPv6PROTO_NONE = 0, /* No protocol assigned */ + IPv6PROTO_STATIC = 1, /* Use static IP */ + IPv6PROTO_AUTOCONF = 2, /* Use ICMPv6 auto-configuration */ + IPv6PROTO_FALLBACK = 3 /* Use auto-configuration with fall back static IP */ }; struct ipv6cfg_s @@ -143,6 +143,7 @@ struct ipv6cfg_s /**************************************************************************** * Public Function Prototypes ****************************************************************************/ + #ifdef __cplusplus #define EXTERN extern "C" extern "C"