apps/fsutils/ipcfg: Add support for IPv6
This commit is contained in:
parent
707e827ded
commit
a627561c8f
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
238
fsutils/ipcfg/ipcfg.h
Normal 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 */
|
568
fsutils/ipcfg/ipcfg_binary.c
Normal file
568
fsutils/ipcfg/ipcfg_binary.c
Normal 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
805
fsutils/ipcfg/ipcfg_text.c
Normal 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 */
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user