ipcfg: Add hooks for future IPv6 support.

This commit adds structures, modifies function prototypes, and renames data to support the future addition of IPv6 support.  This commit does NOT add that IPv6, only the hooks for backward compatible future support.
This commit is contained in:
Gregory Nutt 2020-10-02 10:10:29 -06:00 committed by David Sidrane
parent 536660d062
commit 707e827ded
3 changed files with 217 additions and 85 deletions

View File

@ -46,18 +46,18 @@
#define DEVICE1 "eth0" #define DEVICE1 "eth0"
#define DEVICE2 "eth1" #define DEVICE2 "eth1"
#define BOOTPROTO_MAX BOOTPROTO_FALLBACK #define IPv4PROTO_MAX IPv4PROTO_FALLBACK
/**************************************************************************** /****************************************************************************
* Private Data * Private Data
****************************************************************************/ ****************************************************************************/
static const char *g_proto_name[] = static const char *g_ipv4proto_name[] =
{ {
"none", /* BOOTPROTO_NONE */ "none", /* IPv4PROTO_NONE */
"static", /* BOOTPROTO_STATIC */ "static", /* IPv4PROTO_STATIC */
"dhcp", /* BOOTPROTO_DHCP */ "dhcp", /* IPv4PROTO_DHCP */
"fallback" /* BOOTPROTO_FALLBACK */ "fallback" /* IPv4PROTO_FALLBACK */
}; };
/**************************************************************************** /****************************************************************************
@ -91,10 +91,10 @@ static void ipcfg_dump_addr(FAR const char *variable, in_addr_t address)
static int ipcfg_dump_config(FAR const char *netdev) static int ipcfg_dump_config(FAR const char *netdev)
{ {
struct ipcfg_s ipcfg; struct ipv4cfg_s ipv4cfg;
int ret; int ret;
ret = ipcfg_read(netdev, &ipcfg); ret = ipcfg_read(netdev, (FAR struct ipcfg_s *)&ipv4cfg, AF_INET);
if (ret < 0) if (ret < 0)
{ {
fprintf(stderr, "ERROR: ipcfg_read() failed: %d\n", ret); fprintf(stderr, "ERROR: ipcfg_read() failed: %d\n", ret);
@ -105,19 +105,19 @@ static int ipcfg_dump_config(FAR const char *netdev)
printf("%s:\n", netdev); printf("%s:\n", netdev);
if (ipcfg.proto > BOOTPROTO_MAX) if (ipv4cfg.proto > IPv4PROTO_MAX)
{ {
printf("BOOTPROTO: %d [INVALID]\n", ipcfg.proto); printf("BOOTPROTO: %d [INVALID]\n", ipv4cfg.proto);
} }
else else
{ {
printf("BOOTPROTO: %s\n", g_proto_name[ipcfg.proto]); printf("BOOTPROTO: %s\n", g_ipv4proto_name[ipv4cfg.proto]);
} }
ipcfg_dump_addr("IPADDR: ", ipcfg.ipaddr); ipcfg_dump_addr("IPADDR: ", ipv4cfg.ipaddr);
ipcfg_dump_addr("NETMASK: ", ipcfg.netmask); ipcfg_dump_addr("NETMASK: ", ipv4cfg.netmask);
ipcfg_dump_addr("ROUTER: ", ipcfg.router); ipcfg_dump_addr("ROUTER: ", ipv4cfg.router);
ipcfg_dump_addr("DNS: ", ipcfg.dnsaddr); ipcfg_dump_addr("DNS: ", ipv4cfg.dnsaddr);
return OK; return OK;
} }
@ -128,19 +128,19 @@ static int ipcfg_dump_config(FAR const char *netdev)
static int ipcfg_write_config(FAR const char *netdev) static int ipcfg_write_config(FAR const char *netdev)
{ {
struct ipcfg_s ipcfg; struct ipv4cfg_s ipv4cfg;
int ret; int ret;
ipcfg.proto = BOOTPROTO_DHCP; ipv4cfg.proto = IPv4PROTO_DHCP;
ipcfg.ipaddr = HTONL(0x0a000002); ipv4cfg.ipaddr = HTONL(0x0a000002);
ipcfg.netmask = HTONL(0xffffff00); ipv4cfg.netmask = HTONL(0xffffff00);
ipcfg.router = HTONL(0x0a000001); ipv4cfg.router = HTONL(0x0a000001);
ipcfg.router = HTONL(0x0a000003); ipv4cfg.dnsaddr = HTONL(0x0a000003);
ret = ipcfg_write(netdev, &ipcfg); ret = ipcfg_write(netdev, (FAR struct ipcfg_s *)&ipv4cfg, AF_INET);
if (ret < 0) if (ret < 0)
{ {
fprintf(stderr, "ERROR: ipcfg_read() ipcfg_write: %d\n", ret); fprintf(stderr, "ERROR: ipcfg_write() ipcfg_write: %d\n", ret);
} }
return ret; return ret;

View File

@ -40,19 +40,33 @@
****************************************************************************/ ****************************************************************************/
#define MAX_LINESIZE 80 #define MAX_LINESIZE 80
#define MAX_BOOTPROTO BOOTPROTO_FALLBACK #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 * Private Data
****************************************************************************/ ****************************************************************************/
#if defined(CONFIG_IPCFG_WRITABLE) && !defined(CONFIG_IPCFG_BINARY) #if defined(CONFIG_IPCFG_WRITABLE) && !defined(CONFIG_IPCFG_BINARY)
static const char *g_proto_name[] = static const char *g_ipv4proto_name[] =
{ {
"none", /* BOOTPROTO_NONE */ "none", /* IPv4PROTO_NONE */
"static", /* BOOTPROTO_STATIC */ "static", /* IPv4PROTO_STATIC */
"dhcp", /* BOOTPROTO_DHCP */ "dhcp", /* IPv4PROTO_DHCP */
"fallback" /* BOOTPROTO_FALLBACK */ "fallback" /* IPv4PROTO_FALLBACK */
}; };
#endif #endif
@ -321,7 +335,10 @@ static void ipcfg_putaddr(FAR FILE *stream, FAR const char *variable,
* Input Parameters: * Input Parameters:
* netdev - The network device. For examplel "eth0" * netdev - The network device. For examplel "eth0"
* ipcfg - Pointer to a user provided location to receive the IP * ipcfg - Pointer to a user provided location to receive the IP
* configuration. * configuration. Refers to either struct ipv4cfg_s or
* ipv6cfg_s, depending on the value of af.
* af - Identifies the address family whose IP configuration is
* requested. May be either AF_INET or AF_INET6.
* *
* Returned Value: * Returned Value:
* Zero is returned on success; a negated errno value is returned on any * Zero is returned on success; a negated errno value is returned on any
@ -329,14 +346,16 @@ static void ipcfg_putaddr(FAR FILE *stream, FAR const char *variable,
* *
****************************************************************************/ ****************************************************************************/
int ipcfg_read(FAR const char *netdev, FAR struct ipcfg_s *ipcfg) int ipcfg_read(FAR const char *netdev, FAR void *ipcfg, sa_family_t af)
{ {
#ifdef CONFIG_IPCFG_BINARY #ifdef CONFIG_IPCFG_BINARY
FAR struct ipv4cfg_s *ipv4cfg = (FAR struct ipv4cfg_s *)ipcfg;
struct ipcfg_header_s hdr;
ssize_t nread; ssize_t nread;
int fd; int fd;
int ret; int ret;
DEBUGASSERT(netdev != NULL && ipcfg != NULL); DEBUGASSERT(netdev != NULL && ipv4cfg != NULL && af == AF_INET);
/* Open the file */ /* Open the file */
@ -346,15 +365,41 @@ int ipcfg_read(FAR const char *netdev, FAR struct ipcfg_s *ipcfg)
return fd; return fd;
} }
/* Read the header */
nread = read(fd, &hdr, sizeof(struct ipcfg_header_s));
if (nread < 0)
{
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 */ /* Read the file content */
nread = read(fd, ipcfg, sizeof(struct ipcfg_s)); nread = read(fd, ipv4cfg, sizeof(struct ipv4cfg_s));
if (nread < 0) if (nread < 0)
{ {
ret = -errno; ret = -errno;
fprintf(stderr, "ERROR: Failed to read file: %d\n", ret); fprintf(stderr, "ERROR: Failed to read file: %d\n", ret);
} }
else if (nread != sizeof(struct ipcfg_s)) else if (nread != sizeof(struct ipv4cfg_s))
{ {
ret = -EIO; ret = -EIO;
fprintf(stderr, "ERROR: Bad read size: %ld\n", (long)nread); fprintf(stderr, "ERROR: Bad read size: %ld\n", (long)nread);
@ -364,16 +409,18 @@ int ipcfg_read(FAR const char *netdev, FAR struct ipcfg_s *ipcfg)
ret = OK; ret = OK;
} }
errout_with_fd:
close(fd); close(fd);
return ret; return ret;
#else #else
FAR struct ipv4cfg_s *ipv4cfg = (FAR struct ipv4cfg_s *)ipcfg;
FAR FILE *stream; FAR FILE *stream;
char line[MAX_LINESIZE]; char line[MAX_LINESIZE];
int index; int index;
int ret; int ret;
DEBUGASSERT(netdev != NULL && ipcfg != NULL); DEBUGASSERT(netdev != NULL && ipv4cfg != NULL && af == AF_INET);
/* Open the file */ /* Open the file */
@ -385,7 +432,7 @@ int ipcfg_read(FAR const char *netdev, FAR struct ipcfg_s *ipcfg)
/* Process each line in the file */ /* Process each line in the file */
memset(ipcfg, 0, sizeof(FAR struct ipcfg_s)); memset(ipv4cfg, 0, sizeof(FAR struct ipv4cfg_s));
while (fgets(line, MAX_LINESIZE, stream) != NULL) while (fgets(line, MAX_LINESIZE, stream) != NULL)
{ {
@ -426,45 +473,45 @@ int ipcfg_read(FAR const char *netdev, FAR struct ipcfg_s *ipcfg)
variable, value); variable, value);
} }
} }
else if (strcmp(variable, "BOOTPROTO") == 0) else if (strcmp(variable, "IPv4PROTO") == 0)
{ {
if (strcmp(value, "none") == 0) if (strcmp(value, "none") == 0)
{ {
ipcfg->proto = BOOTPROTO_NONE; ipv4cfg->proto = IPv4PROTO_NONE;
} }
else if (strcmp(value, "static") == 0) else if (strcmp(value, "static") == 0)
{ {
ipcfg->proto = BOOTPROTO_STATIC; ipv4cfg->proto = IPv4PROTO_STATIC;
} }
else if (strcmp(value, "dhcp") == 0) else if (strcmp(value, "dhcp") == 0)
{ {
ipcfg->proto = BOOTPROTO_DHCP; ipv4cfg->proto = IPv4PROTO_DHCP;
} }
else if (strcmp(value, "fallback") == 0) else if (strcmp(value, "fallback") == 0)
{ {
ipcfg->proto = BOOTPROTO_FALLBACK; ipv4cfg->proto = IPv4PROTO_FALLBACK;
} }
else else
{ {
fprintf(stderr, "ERROR: Unrecognized BOOTPROTO: %s=%s\n", fprintf(stderr, "ERROR: Unrecognized IPv4PROTO: %s=%s\n",
variable, value); variable, value);
} }
} }
else if (strcmp(variable, "IPADDR") == 0) else if (strcmp(variable, "IPv4IPADDR") == 0)
{ {
ipcfg->ipaddr = inet_addr(value); ipv4cfg->ipaddr = inet_addr(value);
} }
else if (strcmp(variable, "NETMASK") == 0) else if (strcmp(variable, "IPv4NETMASK") == 0)
{ {
ipcfg->netmask = inet_addr(value); ipv4cfg->netmask = inet_addr(value);
} }
else if (strcmp(variable, "ROUTER") == 0) else if (strcmp(variable, "IPv4ROUTER") == 0)
{ {
ipcfg->router = inet_addr(value); ipv4cfg->router = inet_addr(value);
} }
else if (strcmp(variable, "DNS") == 0) else if (strcmp(variable, "IPv4DNS") == 0)
{ {
ipcfg->dnsaddr = inet_addr(value); ipv4cfg->dnsaddr = inet_addr(value);
} }
else else
{ {
@ -489,7 +536,10 @@ int ipcfg_read(FAR const char *netdev, FAR struct ipcfg_s *ipcfg)
* *
* Input Parameters: * Input Parameters:
* netdev - The network device. For examplel "eth0" * netdev - The network device. For examplel "eth0"
* ipcfg - The IP configuration to be written. * ipcfg - The IP configuration to be written. Refers to either struct
* ipv4cfg_s or ipv6cfg_s, depending on the value of af.
* af - Identifies the address family whose IP configuration is
* to be written. May be either AF_INET or AF_INET6.
* *
* Returned Value: * Returned Value:
* Zero is returned on success; a negated errno value is returned on any * Zero is returned on success; a negated errno value is returned on any
@ -498,14 +548,17 @@ int ipcfg_read(FAR const char *netdev, FAR struct ipcfg_s *ipcfg)
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_IPCFG_WRITABLE #ifdef CONFIG_IPCFG_WRITABLE
int ipcfg_write(FAR const char *netdev, FAR const struct ipcfg_s *ipcfg) int ipcfg_write(FAR const char *netdev, FAR const void *ipcfg,
sa_family_t af)
{ {
#ifdef CONFIG_IPCFG_BINARY #ifdef CONFIG_IPCFG_BINARY
FAR struct ipv4cfg_s *ipv4cfg = (FAR struct ipv4cfg_s *)ipcfg;
struct ipcfg_header_s hdr;
ssize_t nwritten; ssize_t nwritten;
int fd; int fd;
int ret; int ret;
DEBUGASSERT(netdev != NULL && ipcfg != NULL); DEBUGASSERT(netdev != NULL && ipv4cfg != NULL && af == AF_INET);
/* Open the file */ /* Open the file */
@ -515,15 +568,34 @@ int ipcfg_write(FAR const char *netdev, FAR const struct ipcfg_s *ipcfg)
return fd; return fd;
} }
/* Write the file header */
hdr.next = 0;
hdr.type = AF_INET;
nwritten = write(fd, &hdr, sizeof(struct ipcfg_header_s));
if (nwritten < 0)
{
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 */ /* Write the file content */
nwritten = write(fd, ipcfg, sizeof(struct ipcfg_s)); nwritten = write(fd, ipv4cfg, sizeof(struct ipv4cfg_s));
if (nwritten < 0) if (nwritten < 0)
{ {
ret = -errno; ret = -errno;
fprintf(stderr, "ERROR: Failed to write file: %d\n", ret); fprintf(stderr, "ERROR: Failed to write file: %d\n", ret);
} }
else if (nwritten != sizeof(struct ipcfg_s)) else if (nwritten != sizeof(struct ipv4cfg_s))
{ {
ret = -EIO; ret = -EIO;
fprintf(stderr, "ERROR: Bad write size: %ld\n", (long)nwritten); fprintf(stderr, "ERROR: Bad write size: %ld\n", (long)nwritten);
@ -533,14 +605,16 @@ int ipcfg_write(FAR const char *netdev, FAR const struct ipcfg_s *ipcfg)
ret = OK; ret = OK;
} }
errout_with_fd:
close(fd); close(fd);
return ret; return ret;
#else #else
FAR struct ipv4cfg_s *ipv4cfg = (FAR struct ipv4cfg_s *)ipcfg;
FAR FILE *stream; FAR FILE *stream;
int ret; int ret;
DEBUGASSERT(netdev != NULL && ipcfg != NULL); DEBUGASSERT(netdev != NULL && ipv4cfg != NULL && af == AF_INET);
/* Open the file */ /* Open the file */
@ -552,20 +626,20 @@ int ipcfg_write(FAR const char *netdev, FAR const struct ipcfg_s *ipcfg)
/* Format and write the file */ /* Format and write the file */
if ((unsigned)ipcfg->proto > MAX_BOOTPROTO) if ((unsigned)ipv4cfg->proto > MAX_IPv4PROTO)
{ {
fprintf(stderr, "ERROR: Unrecognized BOOTPROTO value: %d\n", fprintf(stderr, "ERROR: Unrecognized IPv4PROTO value: %d\n",
ipcfg->proto); ipv4cfg->proto);
return -EINVAL; return -EINVAL;
} }
fprintf(stream, "DEVICE=%s\n", netdev); fprintf(stream, "DEVICE=%s\n", netdev);
fprintf(stream, "BOOTPROTO=%s\n", g_proto_name[ipcfg->proto]); fprintf(stream, "IPv4PROTO=%s\n", g_ipv4proto_name[ipv4cfg->proto]);
ipcfg_putaddr(stream, "IPADDR", ipcfg->ipaddr); ipcfg_putaddr(stream, "IPv4IPADDR", ipv4cfg->ipaddr);
ipcfg_putaddr(stream, "NETMASK", ipcfg->netmask); ipcfg_putaddr(stream, "IPv4NETMASK", ipv4cfg->netmask);
ipcfg_putaddr(stream, "ROUTER", ipcfg->router); ipcfg_putaddr(stream, "IPv4ROUTER", ipv4cfg->router);
ipcfg_putaddr(stream, "DNS", ipcfg->dnsaddr); ipcfg_putaddr(stream, "IPv4DNS", ipv4cfg->dnsaddr);
/* Close the file and return */ /* Close the file and return */

View File

@ -31,23 +31,17 @@
* Public Types * Public Types
****************************************************************************/ ****************************************************************************/
/* Values for the BOOTPROTO setting */
enum ipcfg_bootproto_e
{
BOOTPROTO_NONE = 0, /* No protocol assigned */
BOOTPROTO_STATIC = 1, /* Use static IP */
BOOTPROTO_DHCP = 2, /* Use DHCP */
BOOTPROTO_FALLBACK = 3 /* Use DHCP with fall back static IP */
};
/* The structure contains the parsed content of the ipcfg-<dev> file. /* The structure contains the parsed content of the ipcfg-<dev> file.
* Summary of file content: * Summary of file content:
* *
* Common Settings:
*
* DEVICE=name * DEVICE=name
* where name is the name of the physical device. * where name is the name of the physical device.
* *
* BOOTPROTO=protocol * IPv4 Settings:
*
* IPv4BOOTPROTO=protocol
* where protocol is one of the following: * where protocol is one of the following:
* *
* none - No protocol selected * none - No protocol selected
@ -58,25 +52,35 @@ enum ipcfg_bootproto_e
* All of the following addresses are in network order. The special value * All of the following addresses are in network order. The special value
* zero is used to indicate that the address is not available: * zero is used to indicate that the address is not available:
* *
* IPADDR=address * IPv4ADDR=address
* where address is the IPv4 address. Used only with static or fallback * where address is the IPv4 address. Used only with static or fallback
* protocols. * protocols.
* *
* NETMASK=address * IPv4NETMASK=address
* where address is the netmask. Used only with static or fallback * where address is the netmask. Used only with static or fallback
* protocols. * protocols.
* *
* ROUTER=address * IPv4ROUTER=address
* where address is the IPv4 default router address. Used only with * where address is the IPv4 default router address. Used only with
* static or fallback protocols. * static or fallback protocols.
* *
* DNS=address * IPv4DNS=address
* where address is a (optional) name server address. * where address is a (optional) name server address.
*/ */
struct ipcfg_s /* Values for the IPv4BOOTPROTO setting */
enum ipv4cfg_bootproto_e
{ {
enum ipcfg_bootproto_e proto; /* Configure for static and/or DHCP */ IPv4PROTO_NONE = 0, /* No protocol assigned */
IPv4PROTO_STATIC = 1, /* Use static IP */
IPv4PROTO_DHCP = 2, /* Use DHCP */
IPv4PROTO_FALLBACK = 3 /* Use DHCP with fall back static IP */
};
struct ipv4cfg_s
{
enum ipv4cfg_bootproto_e proto; /* Configure for static and/or DHCP */
/* The following fields are required for static/fallback configurations */ /* The following fields are required for static/fallback configurations */
@ -89,6 +93,53 @@ struct ipcfg_s
in_addr_t dnsaddr; /* Name server address */ in_addr_t dnsaddr; /* Name server address */
}; };
/* IPv6 Settings:
*
* IPv6BOOTPROTO=protocol
* where protocol is one of the following:
*
* none - No protocol selected
* static - Use static IP
* autoconf - ICMPv6 auto-configuration should be used
* fallback - Use auto-configuration with fall back static IP
*
* All of the following addresses are in network order. The special value
* zero is used to indicate that the address is not available:
*
* IPv6ADDR=address
* where address is the IPv6 address. Used only with static or fallback
* protocols.
*
* IPv6NETMASK=address
* where address is the netmask. Used only with static or fallback
* protocols.
*
* IPv6ROUTER=address
* where address is the IPv6 default router address. Used only with
* static or fallback protocols.
*/
/* Values for the IPv6BOOTPROTO setting */
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 */
};
struct ipv6cfg_s
{
enum ipv6cfg_bootproto_e proto; /* Configure for static and/or autoconfig */
/* The following fields are required for static/fallback configurations */
struct in6_addr ipaddr; /* IPv6 address */
struct in6_addr netmask; /* Network mask */
struct in6_addr router; /* Default router */
};
/**************************************************************************** /****************************************************************************
* Public Function Prototypes * Public Function Prototypes
****************************************************************************/ ****************************************************************************/
@ -110,7 +161,10 @@ extern "C"
* Input Parameters: * Input Parameters:
* netdev - The network device. For examplel "eth0" * netdev - The network device. For examplel "eth0"
* ipcfg - Pointer to a user provided location to receive the IP * ipcfg - Pointer to a user provided location to receive the IP
* configuration. * configuration. Refers to either struct ipv4cfg_s or
* ipv6cfg_s, depending on the value of af.
* af - Identifies the address family whose IP configuration is
* requested. May be either AF_INET or AF_INET6.
* *
* Returned Value: * Returned Value:
* Zero is returned on success; a negated errno value is returned on any * Zero is returned on success; a negated errno value is returned on any
@ -118,7 +172,7 @@ extern "C"
* *
****************************************************************************/ ****************************************************************************/
int ipcfg_read(FAR const char *netdev, FAR struct ipcfg_s *ipcfg); int ipcfg_read(FAR const char *netdev, FAR void *ipcfg, sa_family_t af);
/**************************************************************************** /****************************************************************************
* Name: ipcfg_write * Name: ipcfg_write
@ -128,7 +182,10 @@ int ipcfg_read(FAR const char *netdev, FAR struct ipcfg_s *ipcfg);
* *
* Input Parameters: * Input Parameters:
* netdev - The network device. For examplel "eth0" * netdev - The network device. For examplel "eth0"
* ipcfg - The IP configuration to be written. * ipcfg - The IP configuration to be written. Refers to either struct
* ipv4cfg_s or ipv6cfg_s, depending on the value of af.
* af - Identifies the address family whose IP configuration is
* to be written. May be either AF_INET or AF_INET6.
* *
* Returned Value: * Returned Value:
* Zero is returned on success; a negated errno value is returned on any * Zero is returned on success; a negated errno value is returned on any
@ -137,7 +194,8 @@ int ipcfg_read(FAR const char *netdev, FAR struct ipcfg_s *ipcfg);
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_IPCFG_WRITABLE #ifdef CONFIG_IPCFG_WRITABLE
int ipcfg_write(FAR const char *netdev, FAR const struct ipcfg_s *ipcfg); int ipcfg_write(FAR const char *netdev, FAR const void *ipcfg,
sa_family_t af);
#endif #endif
#undef EXTERN #undef EXTERN
#ifdef __cplusplus #ifdef __cplusplus