1184 lines
32 KiB
C
1184 lines
32 KiB
C
|
|
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipdhcpc6_util.c,v $ $Revision: 1.15.18.3 $
|
|
* $Source: /home/interpeak/CVSRoot/ipdhcpc6/src/ipdhcpc6_util.c,v $
|
|
* $Author: jren $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#include "ipdhcpc6_config.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_clib2.h>
|
|
#include <ipcom_file.h>
|
|
#include <ipcom_os.h>
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_sock6.h>
|
|
#include <ipcom_syslog.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_sysvar.h>
|
|
#include <ipcom_tmo2.h>
|
|
|
|
#include "ipdhcpc6.h"
|
|
#include "ipdhcpc6_h.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
#define IPDHCPC6_ALL_DHCP_RELAY_AGENTS_AND_SERVERS_INIT \
|
|
{{{ 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02 }}}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
typedef struct Ipdhcpc6_util_sysvar_data
|
|
{
|
|
Ip_u32 baselen;
|
|
void *opaque;
|
|
Ipdhcpc6_util_sysvar_foreach_t cb_func;
|
|
} Ipdhcpc6_util_sysvar_data_t;
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
IP_PUBLIC IP_CONST struct Ip_in6_addr ipdhpc6_in6addr_dhcp_servers = IPDHCPC6_ALL_DHCP_RELAY_AGENTS_AND_SERVERS_INIT;
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_strlist
|
|
*===========================================================================
|
|
* Description: Create a null terminated array with with the tokens
|
|
* contained in the original string separated by token
|
|
* Parameters: str - The string to split
|
|
* sep - The separator token
|
|
* Returns: IP_NULL terminated array of tokens.
|
|
*
|
|
*/
|
|
IP_STATIC int
|
|
ipdhcpc6_util_strlist_parse(const char *str,
|
|
const char *sep,
|
|
char **array,
|
|
int array_size)
|
|
{
|
|
const char *ptr;
|
|
char *last;
|
|
char *cstr = ipcom_strdup(str);
|
|
int sz = 0;
|
|
|
|
/* working copy */
|
|
if (cstr == IP_NULL)
|
|
return 0;
|
|
|
|
ptr = ipcom_strtok_r(cstr, sep, &last);
|
|
while (ptr != IP_NULL)
|
|
{
|
|
if (array)
|
|
{
|
|
if (sz < array_size)
|
|
array[sz++] = ipcom_strdup(ptr);
|
|
}
|
|
else
|
|
sz++;
|
|
|
|
ptr = ipcom_strtok_r(IP_NULL, sep, &last);
|
|
}
|
|
|
|
ipdhcpc6_util_free(&cstr);
|
|
return sz;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_sysvar_foreach_parse
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC int
|
|
ipdhcpc6_util_sysvar_foreach_parse(const char *name,
|
|
const char *value,
|
|
int flags,
|
|
void *cookie)
|
|
{
|
|
Ipdhcpc6_util_sysvar_data_t *data = cookie;
|
|
Ip_size_t blen = data->baselen;
|
|
|
|
IPDHCPC6_UNUSED_PARAMETER(flags);
|
|
|
|
if (name[blen] == '.')
|
|
blen++;
|
|
|
|
(*data->cb_func) (name,
|
|
&name[blen],
|
|
value,
|
|
data->opaque);
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_sysvar
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC char *
|
|
ipdhcpc6_util_sysvar(const char *format, va_list ap)
|
|
{
|
|
char buf[128];
|
|
|
|
ipcom_vsnprintf(buf, sizeof(buf), format, ap);
|
|
return ipcom_sysvar_get(buf, IP_NULL, IP_NULL);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_buffer_verify_size
|
|
*===========================================================================
|
|
* Description: Verify that size bytes can be fit into the buffer
|
|
* Parameters: buf - Buffer pointer.
|
|
* size - Size to verisy
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_bool
|
|
ipdhcpc6_util_buffer_verify_size(Ipdhcpc6_util_buffer_t *buf,
|
|
Ip_size_t size)
|
|
{
|
|
Ip_size_t avail = buf->size - buf->offset;
|
|
|
|
if (avail < size)
|
|
{
|
|
/* Allocate what is required, plus 128 bytes. */
|
|
Ip_size_t alloc = size + 128 - avail + buf->size;
|
|
Ip_u8 *bptr;
|
|
|
|
bptr = ipcom_malloc(alloc);
|
|
if (bptr)
|
|
{
|
|
if (buf->size)
|
|
{
|
|
ipcom_memcpy(bptr, buf->head, buf->offset);
|
|
ipdhcpc6_util_free(&buf->head);
|
|
}
|
|
|
|
/* Store new values */
|
|
buf->head = bptr;
|
|
buf->size = alloc;
|
|
}
|
|
else
|
|
{
|
|
/* No go */
|
|
return IP_FALSE;
|
|
}
|
|
}
|
|
|
|
return IP_TRUE;
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_nptoa
|
|
*===========================================================================
|
|
* Description: Converts an IPv6 address and prefix to string representation.
|
|
* Result ends up in a static buffer which is returned.
|
|
* Parameters: ntoa - The NTOA context
|
|
* addr - The IPv6 address.
|
|
* Returns: The address in string form.
|
|
*
|
|
*/
|
|
IP_GLOBAL const char *
|
|
ipdhcpc6_util_nptoa(Ipdhcpc6_util_ntoa_t *ntoa,
|
|
Ipdhcpc6_attr_prefix_t *addr)
|
|
{
|
|
/* Current buffer */
|
|
char* buf = ntoa->ntoa6_buffer[ntoa->ntoa6_index];
|
|
ntoa->ntoa6_index = (Ip_u8) ((ntoa->ntoa6_index + 1) & IPDHCPC6_ADDRESS_ADDRMASK);
|
|
|
|
/* Convert */
|
|
ipcom_inet_ntop(IP_AF_INET6, &addr->addr, buf, IPDHCPC6_ADDRESS_ADDRSIZE - IP_IFNAMSIZ - 1);
|
|
|
|
if (addr->plen != 128)
|
|
{
|
|
char pbuf[16];
|
|
|
|
ipcom_snprintf(pbuf, sizeof(pbuf), "%u", addr->plen);
|
|
ipcom_strncat(buf, "/", IPDHCPC6_ADDRESS_ADDRSIZE - IP_IFNAMSIZ - 1);
|
|
ipcom_strncat(buf, pbuf, IPDHCPC6_ADDRESS_ADDRSIZE - IP_IFNAMSIZ - 1);
|
|
}
|
|
|
|
/* And return */
|
|
return buf;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_ntoa
|
|
*===========================================================================
|
|
* Description: Converts an IPv6 address to string representation. Result
|
|
* ends up in a static buffer which is returned.
|
|
* Parameters: ntoa - The NTOA context
|
|
* addr - The IPv6 address.
|
|
* Returns: The address in string form.
|
|
*
|
|
*/
|
|
IP_GLOBAL const char *
|
|
ipdhcpc6_util_ntoa(Ipdhcpc6_util_ntoa_t *ntoa,
|
|
const struct Ip_in6_addr *addr)
|
|
{
|
|
Ipdhcpc6_attr_prefix_t prefix;
|
|
|
|
ipcom_memcpy(&prefix.addr, addr, sizeof(*addr));
|
|
prefix.plen = 128;
|
|
|
|
return ipdhcpc6_util_nptoa(ntoa, &prefix);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_ip6
|
|
*===========================================================================
|
|
* Description: Convert a string to an IPv6 address and prefix.
|
|
* Parameters: addr - The in6 addr to store the result in.
|
|
* plen - Prefix length.[may be NULL]
|
|
* str - String to parse
|
|
* Returns: IP_TRUE if successful, IP_FALSE otherwise.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipdhcpc6_util_ip6(struct Ip_in6_addr *addr,
|
|
Ip_u32 *plen,
|
|
char *str)
|
|
{
|
|
char *a;
|
|
char *p = IP_NULL;
|
|
char *n;
|
|
char *strval = ipcom_strdup(str);
|
|
Ip_bool retval = IP_FALSE;
|
|
|
|
if (strval == IP_NULL)
|
|
return IP_FALSE;
|
|
|
|
/* Get first token */
|
|
if ((a = ipcom_strtok_r(strval, " \t/", &n)) == IP_NULL)
|
|
goto errout;
|
|
|
|
/* Get second token */
|
|
if (plen)
|
|
{
|
|
if ((p = ipcom_strtok_r(IP_NULL, " \t/", &n)) == IP_NULL)
|
|
goto errout;
|
|
}
|
|
|
|
/* Convert address */
|
|
if (ipcom_inet_pton(IP_AF_INET6, a, addr) != 1)
|
|
goto errout;
|
|
|
|
if (plen)
|
|
{
|
|
int prefix = ipcom_atoi(p);
|
|
|
|
/* Sanity */
|
|
if (prefix < 0 || prefix > 128)
|
|
goto errout;
|
|
|
|
/* Store it */
|
|
*plen = (Ip_u8) prefix;
|
|
}
|
|
|
|
retval = IP_TRUE;
|
|
|
|
errout:
|
|
ipdhcpc6_util_free(&strval);
|
|
return retval;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_sysvar_ip6
|
|
*===========================================================================
|
|
* Description: Read a sysvar variable and convert it to an IPv6 address and
|
|
* prefix.
|
|
* Parameters: addr - The in6 addr to store the result in.
|
|
* plen - Prefix length.[may be NULL]
|
|
* format - Format string
|
|
* ... - Arguments.
|
|
* Returns: IP_TRUE if successful, IP_FALSE otherwise.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipdhcpc6_util_sysvar_ip6(struct Ip_in6_addr *addr,
|
|
Ip_u32 *plen,
|
|
const char *format,
|
|
/* args*/ ...)
|
|
{
|
|
char *strval;
|
|
va_list ap;
|
|
Ip_bool retval = IP_FALSE;
|
|
|
|
/* Your basic memset */
|
|
ipcom_memset(addr, 0, sizeof(*addr));
|
|
|
|
va_start(ap, format);
|
|
strval = ipdhcpc6_util_sysvar(format, ap);
|
|
va_end(ap);
|
|
|
|
|
|
/* Grab the sysvar */
|
|
if (strval)
|
|
{
|
|
retval = ipdhcpc6_util_ip6(addr, plen, strval);
|
|
ipdhcpc6_util_free(&strval);
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_sysvar_bool
|
|
*===========================================================================
|
|
* Description: Parse a boolean value
|
|
* Parameters: defval - The default value
|
|
* format - The format string
|
|
* ... - arguments
|
|
* Returns: The boolean result.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipdhcpc6_util_sysvar_bool(Ip_bool defval, const char *format, /* args*/ ...)
|
|
{
|
|
va_list ap;
|
|
char *buf;
|
|
|
|
va_start(ap, format);
|
|
buf = ipdhcpc6_util_sysvar(format, ap);
|
|
va_end(ap);
|
|
|
|
/* Parse the value */
|
|
if (buf)
|
|
{
|
|
defval = ipdhcpc6_util_bool(buf);
|
|
ipdhcpc6_util_free(&buf);
|
|
}
|
|
|
|
return defval;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_sysvar_mode
|
|
*===========================================================================
|
|
* Description: Parse a mode value
|
|
* Parameters: defval - The default value
|
|
* format - The format string
|
|
* ... - arguments
|
|
* Returns: The int result.
|
|
*
|
|
*/
|
|
IP_GLOBAL int
|
|
ipdhcpc6_util_sysvar_mode(Ip_bool defval, const char *format, /* args*/ ...)
|
|
{
|
|
va_list ap;
|
|
char *buf;
|
|
|
|
va_start(ap, format);
|
|
buf = ipdhcpc6_util_sysvar(format, ap);
|
|
va_end(ap);
|
|
|
|
/* Parse the value */
|
|
if (buf)
|
|
{
|
|
defval = ipdhcpc6_util_mode(buf);
|
|
ipdhcpc6_util_free(&buf);
|
|
}
|
|
|
|
return defval;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_sysvar_int
|
|
*===========================================================================
|
|
* Description: Parse an integer value
|
|
* Parameters: defval - The default value
|
|
* format - The format string
|
|
* ... - arguments
|
|
* Returns: The integer result.
|
|
*
|
|
*/
|
|
IP_GLOBAL int
|
|
ipdhcpc6_util_sysvar_int(int defval, const char *format, /* args*/ ...)
|
|
{
|
|
va_list ap;
|
|
char *buf;
|
|
|
|
va_start(ap, format);
|
|
buf = ipdhcpc6_util_sysvar(format, ap);
|
|
va_end(ap);
|
|
|
|
/* Parse the value */
|
|
if (buf)
|
|
{
|
|
/* Non zero? */
|
|
defval = (int)ipcom_strtoul(buf, IP_NULL, 10);
|
|
ipdhcpc6_util_free(&buf);
|
|
}
|
|
|
|
return defval;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_hexarray
|
|
*===========================================================================
|
|
* Description: Convert a string to a hexarray
|
|
* Parameters: buf - Where to store the result.
|
|
* kstr - The key string to convert.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipdhcpc6_util_hexarray(Ipdhcpc6_util_buffer_t *buf,
|
|
char *kstr)
|
|
{
|
|
Ip_size_t len;
|
|
if (ipcom_strncasecmp(kstr, "0x", 2) == 0)
|
|
{
|
|
Ip_u32 i;
|
|
|
|
/* Skip the '0x' */
|
|
kstr += 2;
|
|
|
|
/* Each two bytes are a hex value */
|
|
len = ipcom_strlen(kstr);
|
|
len >>= 1;
|
|
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
Ip_u8 value;
|
|
char bptr[3];
|
|
|
|
bptr[2] = '\0';
|
|
|
|
/* Copy the first two bytes */
|
|
ipcom_memcpy(bptr, kstr, 2);
|
|
|
|
/* Parse them */
|
|
value = (Ip_u8) ipcom_strtoul(bptr, IP_NULL, 16);
|
|
|
|
/* Store */
|
|
ipdhcpc6_util_buffer_append(buf, &value, 1);
|
|
|
|
/* Read next two */
|
|
kstr += 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Calculate the length */
|
|
len = ipcom_strlen(kstr);
|
|
|
|
/* Append entire string */
|
|
ipdhcpc6_util_buffer_append(buf, kstr, len);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_sysvar_hexarray
|
|
*===========================================================================
|
|
* Description: Read a sysvar variable and convert to an hexarray
|
|
* Parameters: buf - Where to store the hexarray
|
|
* format - Format string
|
|
* ... - Arguments.
|
|
* Returns: IP_TRUE if successful, IP_FALSE otherwise.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipdhcpc6_util_sysvar_hexarray(Ipdhcpc6_util_buffer_t *buf,
|
|
const char *format,
|
|
/* args*/ ...)
|
|
{
|
|
va_list ap;
|
|
char *kstr;
|
|
|
|
va_start(ap, format);
|
|
kstr = ipdhcpc6_util_sysvar(format, ap);
|
|
va_end(ap);
|
|
|
|
/* Parse the value */
|
|
if (kstr)
|
|
{
|
|
if (ipcom_strlen(kstr) > 0)
|
|
{
|
|
ipdhcpc6_util_hexarray(buf, kstr);
|
|
|
|
/* Non zero? */
|
|
ipdhcpc6_util_free(&kstr);
|
|
|
|
/* Found & Converted */
|
|
return IP_TRUE;
|
|
}
|
|
|
|
ipdhcpc6_util_free(&kstr);
|
|
}
|
|
|
|
return IP_FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_bool
|
|
*===========================================================================
|
|
* Description: Interpret a value as 'true' or 'false'
|
|
* Parameters: value - The value to interpret
|
|
* Returns: IP_TRUE if successful, IP_FALSE otherwise.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipdhcpc6_util_bool(const char *value)
|
|
{
|
|
/* Enabled? */
|
|
if (ipcom_strcasecmp(value, "enable") == 0 ||
|
|
ipcom_strcasecmp(value, "true") == 0 ||
|
|
ipcom_strcasecmp(value, "yes") == 0)
|
|
return IPDHCPC6_MODE_ENABLED;
|
|
|
|
/* Disabled? */
|
|
if (ipcom_strcasecmp(value, "disable") == 0 ||
|
|
ipcom_strcasecmp(value, "false") == 0 ||
|
|
ipcom_strcasecmp(value, "no") == 0)
|
|
return IPDHCPC6_MODE_DISABLED;
|
|
|
|
/* Non zero? */
|
|
if (ipcom_strtoul(value, IP_NULL, 10))
|
|
return IPDHCPC6_MODE_ENABLED;
|
|
|
|
return IPDHCPC6_MODE_DISABLED;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_mode
|
|
*===========================================================================
|
|
* Description: Interpret a value as a mode
|
|
* Parameters: value - The value to interpret
|
|
* Returns: The mode
|
|
*
|
|
*/
|
|
IP_GLOBAL int
|
|
ipdhcpc6_util_mode(const char *value)
|
|
{
|
|
/* Enabled? */
|
|
if (ipcom_strcasecmp(value, "enable") == 0 ||
|
|
ipcom_strcasecmp(value, "true") == 0 ||
|
|
ipcom_strcasecmp(value, "yes") == 0)
|
|
return IPDHCPC6_MODE_ENABLED;
|
|
|
|
/* Disabled? */
|
|
if (ipcom_strcasecmp(value, "disable") == 0 ||
|
|
ipcom_strcasecmp(value, "false") == 0 ||
|
|
ipcom_strcasecmp(value, "no") == 0)
|
|
return IPDHCPC6_MODE_DISABLED;
|
|
|
|
if (ipcom_strcasecmp(value, "automatic") == 0 ||
|
|
ipcom_strcasecmp(value, "auto") == 0)
|
|
return IPDHCPC6_MODE_AUTOMATIC;
|
|
|
|
return IPDHCPC6_MODE_DISABLED;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_sysvar_foreach
|
|
*===========================================================================
|
|
* Description: Iterate and expand tables in sysvar.
|
|
* Parameters: cb_func - The dhcpc6 foreach callback
|
|
* cookie - Opaque data.
|
|
* format - The format key
|
|
* ... - Arguments
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipdhcpc6_util_sysvar_foreach(Ipdhcpc6_util_sysvar_foreach_t cb_func,
|
|
void *cookie,
|
|
const char *format,
|
|
/* args*/ ...)
|
|
{
|
|
Ipdhcpc6_util_sysvar_data_t data;
|
|
va_list ap;
|
|
char buf[128];
|
|
|
|
va_start(ap, format);
|
|
ipcom_vsnprintf(buf, sizeof(buf), format, ap);
|
|
va_end(ap);
|
|
|
|
data.baselen = (Ip_u32)ipcom_strlen(buf);
|
|
data.cb_func = cb_func;
|
|
data.opaque = cookie;
|
|
|
|
ipcom_sysvar_for_each(buf,
|
|
(Ipcom_sysvar_for_each)ipdhcpc6_util_sysvar_foreach_parse,
|
|
&data);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_strdup
|
|
*===========================================================================
|
|
* Description: Do a va list strdup
|
|
* Parameters: format - The format string
|
|
* ... - arguments
|
|
* Returns: resulting string.
|
|
*
|
|
*/
|
|
IP_GLOBAL char *
|
|
ipdhcpc6_util_strdup(const char *format,
|
|
/* args*/ ...)
|
|
{
|
|
char buf[128];
|
|
va_list ap;
|
|
|
|
va_start(ap, format);
|
|
ipcom_vsnprintf(buf, sizeof(buf), format, ap);
|
|
va_end(ap);
|
|
|
|
return ipcom_strdup(buf);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_strlist
|
|
*===========================================================================
|
|
* Description: Create a null terminated array with with the tokens
|
|
* contained in the original string separated by token
|
|
* Parameters: str - The string to split
|
|
* sep - The separator token
|
|
* Returns: IP_NULL terminated array of tokens.
|
|
*
|
|
*/
|
|
IP_GLOBAL char **
|
|
ipdhcpc6_util_strlist(const char *str,
|
|
const char *sep)
|
|
{
|
|
int sz;
|
|
|
|
sz = ipdhcpc6_util_strlist_parse(str, sep, IP_NULL, 0);
|
|
if (sz)
|
|
{
|
|
char **array = ipcom_calloc((Ip_size_t)(sz + 1), sizeof(char *));
|
|
if (array)
|
|
{
|
|
ipdhcpc6_util_strlist_parse(str, sep, array, sz);
|
|
return array;
|
|
}
|
|
}
|
|
|
|
return IP_NULL;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_strtok
|
|
*===========================================================================
|
|
* Description: split a string by the specific char ',' or ';'
|
|
* Parameters: s - The string to split
|
|
* split_char - retrun the split char which is used to spit for this string
|
|
* Returns: the splited string or IP_NULL if not found.
|
|
*
|
|
*/
|
|
|
|
IP_GLOBAL char *
|
|
ipdhcpc6_util_strtok(char **s, char *split_char)
|
|
{
|
|
char *start;
|
|
char *stop;
|
|
|
|
if (*s == IP_NULL || split_char == IP_NULL)
|
|
return IP_NULL;
|
|
|
|
start = *s;
|
|
while (*start != '\0' && ipcom_strchr(",;", *start) != IP_NULL)
|
|
start++;
|
|
stop = start;
|
|
while (*stop != '\0' && ipcom_strchr(",;", *stop) == IP_NULL)
|
|
stop++;
|
|
if (*stop != '\0')
|
|
{
|
|
*split_char = *stop;
|
|
*stop++ = '\0';
|
|
}
|
|
else
|
|
*split_char = '\0';
|
|
*s = stop;
|
|
|
|
return ipcom_strlen(start) ? start : IP_NULL;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_sysvar_strlist
|
|
*===========================================================================
|
|
* Description: Retrieve a string from a sysvar and split it into appropriate
|
|
* substrings.
|
|
* Parameters: format - The format string
|
|
* ... - arguments
|
|
* Returns: The string array
|
|
*
|
|
*/
|
|
IP_GLOBAL char **
|
|
ipdhcpc6_util_sysvar_strlist(const char *format,
|
|
/* args*/ ...)
|
|
{
|
|
va_list ap;
|
|
char *buf;
|
|
|
|
va_start(ap, format);
|
|
buf = ipdhcpc6_util_sysvar(format, ap);
|
|
va_end(ap);
|
|
|
|
/* Parse the value */
|
|
if (buf)
|
|
{
|
|
char **array = ipdhcpc6_util_strlist(buf, ",; \t");
|
|
ipdhcpc6_util_free(&buf);
|
|
return array;
|
|
}
|
|
|
|
return IP_NULL;
|
|
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_strlist_free
|
|
*===========================================================================
|
|
* Description: Frees a null terminated string array and its contents
|
|
* Parameters: strarrp - [IN/OUT] The string array. Will be set to IP_NULL.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipdhcpc6_util_strlist_free(char ***strarrp)
|
|
{
|
|
char **strarr = *strarrp;
|
|
|
|
if (strarr)
|
|
{
|
|
int i = 0;
|
|
/* Free all elements */
|
|
while (strarr[i] != IP_NULL)
|
|
ipdhcpc6_util_free(&strarr[i++]);
|
|
|
|
/* Free the array itself */
|
|
ipdhcpc6_util_free(&strarr);
|
|
}
|
|
|
|
*strarrp = IP_NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_sock_clear
|
|
*===========================================================================
|
|
* Description: Clear errno on socket.
|
|
* Parameters: fd - File descriptor
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipdhcpc6_util_sock_clear(Ip_fd fd)
|
|
{
|
|
int err;
|
|
Ip_socklen_t errlen;
|
|
|
|
errlen = sizeof(int);
|
|
(void)ipcom_getsockopt(fd, IP_SOL_SOCKET, IP_SO_ERROR, &err, &errlen);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_buffer_init
|
|
*===========================================================================
|
|
* Description: Initialize a buffer structure.
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipdhcpc6_util_buffer_init(Ipdhcpc6_util_buffer_t *buf)
|
|
{
|
|
ipcom_memset(buf, 0, sizeof(*buf));
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_buffer_release
|
|
*===========================================================================
|
|
* Description: Release any resources associated with a buffer
|
|
* Parameters: buf - Buffer pointer.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipdhcpc6_util_buffer_release(Ipdhcpc6_util_buffer_t *buf)
|
|
{
|
|
if (buf->head)
|
|
ipdhcpc6_util_free(&buf->head);
|
|
ipcom_memset(buf, 0, sizeof(*buf));
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_buffer_append
|
|
*===========================================================================
|
|
* Description: Append data to a buffer pointer.
|
|
* Parameters: buf - Buffer pointer.
|
|
* data - Data block
|
|
* size - Size of data block.
|
|
* Returns: IP_TRUE if successful.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipdhcpc6_util_buffer_append(Ipdhcpc6_util_buffer_t *buf,
|
|
void *data,
|
|
Ip_size_t size)
|
|
{
|
|
/* Verify size */
|
|
if (ipdhcpc6_util_buffer_verify_size(buf, size))
|
|
{
|
|
/* Copy the data */
|
|
ipcom_memcpy(&buf->head[buf->offset], data, size);
|
|
|
|
/* Move offset forward */
|
|
buf->offset += size;
|
|
|
|
/* Report success */
|
|
return IP_TRUE;
|
|
}
|
|
|
|
return IP_FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_buffer_htonl
|
|
*===========================================================================
|
|
* Description: Append 32bit integer in network byte order
|
|
* Parameters: buf - Buffer pointer.
|
|
* val - integer
|
|
* Returns: IP_TRUE if successful.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipdhcpc6_util_buffer_htonl(Ipdhcpc6_util_buffer_t *buf,
|
|
Ip_u32 val)
|
|
{
|
|
Ip_u32 nval = ip_htonl(val);
|
|
return ipdhcpc6_util_buffer_append(buf, &nval, 4);
|
|
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_buffer_htons
|
|
*===========================================================================
|
|
* Description: Append 16bit integer in network byte order
|
|
* Parameters: buf - Buffer pointer.
|
|
* val - integer
|
|
* Returns: IP_TRUE if successful.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipdhcpc6_util_buffer_htons(Ipdhcpc6_util_buffer_t *buf,
|
|
Ip_u16 val)
|
|
{
|
|
Ip_u16 nval = ip_htons(val);
|
|
return ipdhcpc6_util_buffer_append(buf, &nval, 2);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_free
|
|
*===========================================================================
|
|
* Description: Free and reset a pointer
|
|
* Parameters: ptrp - Pointer to pointer
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipdhcpc6_util_free(void *ptrp)
|
|
{
|
|
void **vptr = ptrp;
|
|
void *ptr = *vptr;
|
|
if (ptr)
|
|
ipcom_free(ptr);
|
|
*vptr = IP_NULL;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_ioctl
|
|
*===========================================================================
|
|
* Description: Do an IOCTL
|
|
* Parameters: req - The ioctl
|
|
* data - Parameter data
|
|
* new_vr - vr index
|
|
* Returns: The return value
|
|
*
|
|
*/
|
|
IP_GLOBAL int
|
|
ipdhcpc6_util_ioctl(unsigned long req, void *data, int new_vr)
|
|
{
|
|
Ip_fd tfd;
|
|
int ret;
|
|
#if IPCOM_VR_MAX > 1
|
|
int cur_vr = ipcom_proc_vr_get();
|
|
|
|
if (cur_vr != new_vr)
|
|
ipcom_proc_vr_set(new_vr);
|
|
#endif
|
|
|
|
/* Need a socket to do ioctls on */
|
|
tfd = ipcom_socket(IP_AF_INET6, IP_SOCK_DGRAM, IP_IPPROTO_UDP);
|
|
|
|
if (tfd == IP_INVALID_SOCKET)
|
|
{
|
|
ret = -IP_ERRNO_EINVAL;
|
|
goto restore_vr;
|
|
}
|
|
|
|
ret = ipcom_socketioctl(tfd, req, data);
|
|
if (ret < 0)
|
|
{
|
|
/* LOG */
|
|
IPCOM_LOG3(WARNING,
|
|
"IOCTL Failed for %x VR [%d], errno = %d",
|
|
req,
|
|
new_vr,
|
|
ipcom_errno);
|
|
}
|
|
|
|
/* Close the socket */
|
|
ipcom_socketclose(tfd);
|
|
|
|
restore_vr:
|
|
|
|
#if IPCOM_VR_MAX > 1
|
|
if (cur_vr != new_vr)
|
|
ipcom_proc_vr_set(cur_vr);
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_util_parse_fqdn
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters: fullName - FQDN
|
|
* result - result after conversion
|
|
* len - buffer length of result pointing to
|
|
* Returns:
|
|
*
|
|
*/
|
|
|
|
|
|
IP_GLOBAL void
|
|
ipdhcpc6_util_parse_fqdn(const char *fullName, char *result, Ip_u8 len)
|
|
{
|
|
Ip_u8 tLen = 0;
|
|
Ip_u8 rLen = 0;
|
|
ip_assert(fullName);
|
|
ip_assert(result);
|
|
if (ipcom_strlen(fullName)>=len)
|
|
{
|
|
IPCOM_LOG0 (ERR, "no buffer for parsing fqdn option");
|
|
return;
|
|
}
|
|
while(fullName[rLen]!='\0')
|
|
{
|
|
tLen = fullName[rLen];
|
|
if (tLen==0)
|
|
{
|
|
result[rLen]='\0';
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
result[rLen]='.';
|
|
ipcom_memcpy(result+rLen+1, fullName+rLen+1, tLen);
|
|
}
|
|
rLen += tLen+1;
|
|
}
|
|
|
|
ipcom_memmove(result, result+1, rLen);
|
|
result[rLen] = '\0';
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_if_nametoindex
|
|
*===========================================================================
|
|
* Description: return interface index
|
|
* Parameters: ifname - interface name
|
|
* new_vr - vr index
|
|
* Returns: The return value
|
|
*
|
|
*/
|
|
IP_GLOBAL Ip_u32
|
|
ipdhcpc6_if_nametoindex(char *ifname, int new_vr)
|
|
{
|
|
Ip_u32 if_index;
|
|
#if IPCOM_VR_MAX > 1
|
|
int cur_vr = ipcom_proc_vr_get();
|
|
|
|
if (cur_vr != new_vr)
|
|
ipcom_proc_vr_set(new_vr);
|
|
#endif
|
|
|
|
if_index = ipcom_if_nametoindex(ifname);
|
|
|
|
#if IPCOM_VR_MAX > 1
|
|
if (cur_vr != new_vr)
|
|
ipcom_proc_vr_set(cur_vr);
|
|
#endif
|
|
|
|
return if_index;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_if_indextoname
|
|
*===========================================================================
|
|
* Description: return interface index
|
|
* Parameters: ifindex - interface index
|
|
* ifname - interface name
|
|
* new_vr - vr index
|
|
* Returns: The return value
|
|
*
|
|
*/
|
|
IP_GLOBAL char *
|
|
ipdhcpc6_if_indextoname(Ip_u32 ifindex, char *ifname, int new_vr)
|
|
{
|
|
char *ret_ifname;
|
|
#if IPCOM_VR_MAX > 1
|
|
int cur_vr = ipcom_proc_vr_get();
|
|
|
|
if (cur_vr != new_vr)
|
|
ipcom_proc_vr_set(new_vr);
|
|
#endif
|
|
|
|
ret_ifname = ipcom_if_indextoname(ifindex, ifname);
|
|
|
|
#if IPCOM_VR_MAX > 1
|
|
if (cur_vr != new_vr)
|
|
ipcom_proc_vr_set(cur_vr);
|
|
#endif
|
|
|
|
return ret_ifname;
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|