apps/fsutils/ipcfg: Add support for IPv6

This commit is contained in:
Gregory Nutt 2020-10-02 15:43:24 -06:00 committed by Xiang Xiao
parent 707e827ded
commit a627561c8f
9 changed files with 2166 additions and 499 deletions

View File

@ -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

View File

@ -27,6 +27,8 @@
#include <sys/mount.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <debug.h>
#include <arpa/inet.h>
@ -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

View File

@ -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 <varialble>=<value> 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

View File

@ -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

View File

@ -26,49 +26,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <debug.h>
#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 <variable>=<address> 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 <variable>=<value> 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

238
fsutils/ipcfg/ipcfg.h Normal file
View File

@ -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 <nuttx/config.h>
#include <stdint.h>
#include <netinet/in.h>
#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 */

View File

@ -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 <nuttx/config.h>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <debug.h>
#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 */

805
fsutils/ipcfg/ipcfg_text.c Normal file
View File

@ -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 <nuttx/config.h>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <ctype.h>
#include <debug.h>
#include <arpa/inet.h>
#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 <variable>=<address> 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 <variable>=<address> 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 <variable>=<value> 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 <variable>=<value> 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 */

View File

@ -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"