Files
m241Neelima/components/ip_net2-6.9/ipmip/src/ipmip_util.c
T
2026-07-30 11:19:44 +05:30

1496 lines
38 KiB
C

/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_util.c,v $ $Revision: 1.24.10.5 $
* $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_util.c,v $
* $Author: svc-cmnet $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipmip_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_err.h>
#include <ipcom_list.h>
#include <ipcom_os.h>
#include <ipcom_sock.h>
#include <ipcom_sock2.h>
#include <ipcom_sysctl.h>
#include <ipcom_syslog.h>
#include <ipcom_sysvar.h>
#include <ipcom_clib2.h>
#include <ipcom_inet.h>
#ifdef IPMIP_USE_INET6
#include <ipcom_sock6.h>
#endif
#include <ipmip.h>
#include <private/ipmip_util.h>
#include <private/ipmip_context.h>
#include <private/ipmip_sysvar.h>
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#define IPMIP_CMD_HDRSIZE 20
#define IPCOM_SYSLOG_PRIORITY IPCOM_LOG_DEBUG2
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPMIP
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
struct Ipmip_util_cbinfo
{
Ipmip_context_t *ctx;
Ipmip_proc_t *proc;
Ipmip_util_hash_foreach_t func;
void *arg1;
void *arg2;
};
struct Ipmip_util_freeinfo
{
Ipmip_util_hash_free_t func;
Ipcom_hash *hash;
};
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
static Ipmip_sysvar_key_map_t ipmip_util_sysvar_ops[] =
{
{ IPCOM_LOG_EMERG, "emerg" },
{ IPCOM_LOG_EMERG, "emergency" },
{ IPCOM_LOG_CRIT, "crit" },
{ IPCOM_LOG_CRIT, "critical" },
{ IPCOM_LOG_ERR, "err" },
{ IPCOM_LOG_ERR, "error" },
{ IPCOM_LOG_WARNING, "warn" },
{ IPCOM_LOG_WARNING, "warning" },
{ IPCOM_LOG_NOTICE, "notice" },
{ IPCOM_LOG_INFO, "info" },
{ IPCOM_LOG_DEBUG, "debug" },
{ IPCOM_LOG_DEBUG2, "debug2" },
{ 0, 0 }
};
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmip6_bc_purge_bc
*===========================================================================
* Description: Will purge the indicated binding cache entry.
* Parameters: bc - The binding cache entry.
* Returns: IP_TRUE
*
*/
IP_STATIC void
ipmip_util_hash_free_cb(void *entry,
struct Ipmip_util_freeinfo *cbinfo)
{
ipcom_hash_remove(cbinfo->hash, entry);
if (cbinfo->func)
(*cbinfo->func) (entry);
else
ipcom_free(entry);
}
/*
*===========================================================================
* ipmip6_bc_purge_bc
*===========================================================================
* Description: Will purge the indicated binding cache entry.
* Parameters: bc - The binding cache entry.
* Returns: IP_TRUE
*
*/
IP_STATIC void
ipmip_util_hash_foreach_cb(void *entry,
struct Ipmip_util_cbinfo *cbinfo)
{
/* Invoke with all parameters */
(*cbinfo->func) (cbinfo->ctx, cbinfo->proc, entry, cbinfo->arg1, cbinfo->arg2);
}
IP_STATIC void
ipmip_util_print_tabs(int tabs)
{
while (tabs--)
ipcom_printf("\t");
}
IP_STATIC void
ipmip_util_print_hdr(Ipmip_proc_t *proc,
const char *header,
Ip_size_t hdr_size,
const char *delim)
{
unsigned int i = ipcom_strlen(header);
i = IP_MIN(i, hdr_size);
ipcom_memset(proc->ntop.ntop_pbuf, ' ', hdr_size - i);
proc->ntop.ntop_pbuf[hdr_size - i] = '\0';
ipcom_printf("%s%s%s", header, i? delim : "", proc->ntop.ntop_pbuf);
}
/*
*===========================================================================
* ipmip_util_identprintf
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipmip_util_bidentprintf(Ipmip_proc_t *proc,
int tabs,
char *tmp)
{
char *sep;
IPMIP_UNUSED_PARAMETER(proc);
while ((sep = ipcom_strstr(tmp, IP_LF)) != IP_NULL)
{
if (sep == tmp)
ipcom_printf(IP_LF);
else
{
*sep = '\0';
ipmip_util_print_tabs(tabs);
ipcom_printf("%s"IP_LF, tmp);
sep += ipcom_strlen(IP_LF);
if (ipcom_strlen(sep) == 0)
return;
tmp = sep;
}
}
ipmip_util_print_tabs(tabs);
ipcom_printf(tmp);
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipmip_util_vstrdup
*===========================================================================
* Description: Do a strdup on a varargs format list
* Parameters: format - The format
* ap - The 'printf' arguments.
* Returns: An allocated string created using the format and arguments
*
*/
IP_GLOBAL char *
ipmip_util_vstrdup(const char *format,
va_list ap)
{
char *buf = IP_NULL;
Ip_size_t slen;
buf = ipcom_malloc(256);
if (buf == IP_NULL)
return IP_NULL;
/**/
slen = ipcom_vsnprintf(buf, 256, format, ap);
if (slen >= 256)
{
ipcom_free(buf);
return IP_NULL;
}
return buf;
}
/*
*===========================================================================
* ipmip_util_strdup
*===========================================================================
* Description: Do a strdup on a varargs format list
* Parameters: format - The format
* ... - The 'printf' arguments.
* Returns: An allocated string created using the format and arguments
*
*/
IP_GLOBAL char *
ipmip_util_strdup(const char *format,
/* args */ ...)
{
va_list ap;
char *buf;
va_start(ap, format);
buf = ipmip_util_vstrdup(format, ap);
va_end(ap);
return buf;
}
/*
*===========================================================================
* ipmip_util_strnlen
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_size_t
ipmip_util_strnlen(const char *str,
Ip_size_t mlen)
{
Ip_size_t sz = 0;
for (; sz < mlen && *str != '\0'; sz++)
str++;
return sz;
}
/*
*===========================================================================
* ipmip_util_strnlen
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL const char *
ipmip_util_strnchr(const char *str,
const char ch,
Ip_size_t mlen)
{
Ip_size_t sz = 0;
for (; sz < mlen && *str != '\0'; sz++)
{
if (*str == ch)
return str;
}
/**/
return IP_NULL;
}
/*
*===========================================================================
* ipmip_util_sock_clear
*===========================================================================
* Description: Clear error on socket
* Parameters: fd - The filedescriptor to clear
* Returns:
*
*/
IP_GLOBAL void
ipmip_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);
}
/*
*===========================================================================
* ipmip_util_tunnel_to_proto
*===========================================================================
* Description: Convert a tunnel index number to an internet protocol
* Parameters: tunnel - Tunnel index
* Returns: Internet protocol or 0 if no match.
*
*/
IP_GLOBAL Ip_u8
ipmip_util_tunnel_to_proto(Ip_u8 tunnel)
{
switch (tunnel)
{
case IPMIP_TUNNELTYPE_IPIP:
return IP_IPPROTO_IPIP;
case IPMIP_TUNNELTYPE_GRE:
case IPMIP_TUNNELTYPE_GRE6:
return IP_IPPROTO_GRE;
case IPMIP_TUNNELTYPE_MINENC:
return IP_IPPROTO_MOBILE;
case IPMIP_TUNNELTYPE_IP6IP6:
return IP_IPPROTO_IPV6;
default:
return 0;
}
}
/*
*===========================================================================
* ipmip_util_tunnel_to_desc
*===========================================================================
* Description: Convert a tunnel index number to a human readable description
* Parameters: tunnel - Tunnel index
* Returns: Internet protocol or 0 if no match.
*
*/
IP_GLOBAL const char *
ipmip_util_tunnel_to_desc(Ip_u8 tunnel)
{
switch (tunnel)
{
case IPMIP_TUNNELTYPE_IPIP:
return "inet.ipip";
case IPMIP_TUNNELTYPE_GRE:
return "inet.gre";
case IPMIP_TUNNELTYPE_GRE6:
return "inet6.gre";
case IPMIP_TUNNELTYPE_MINENC:
return "inet.minenc";
case IPMIP_TUNNELTYPE_IP6IP6:
return "inet6.ip6ip6";
default:
return "unknown";
}
}
IP_GLOBAL Ip_u8
ipmip_util_tunnelmask_to_type(Ip_u32 mask)
{
int i;
if (mask == 0)
return IPMIP_TUNNELTYPE_NONE;
i = ipcom_ffs(mask);
if (i == 0 || i > IPMIP_TUNNELTYPE_MAX)
return IPMIP_TUNNELTYPE_NONE;
return i - 1;
}
/*
*===========================================================================
* ipmip_util_proto_to_tunnel
*===========================================================================
* Description: Convert a protocol number to a tunnel index
* Parameters: proto - Protocol number
* Returns: Tunnel index or IPMIP4_TUNNELTYPE_NONE if no match.
*
*/
IP_GLOBAL Ip_u8
ipmip_util_proto_to_tunnel(Ip_u8 proto)
{
switch (proto)
{
case IP_IPPROTO_IPIP:
return IPMIP_TUNNELTYPE_IPIP;
case IP_IPPROTO_GRE:
return IPMIP_TUNNELTYPE_GRE;
case IP_IPPROTO_MOBILE:
return IPMIP_TUNNELTYPE_MINENC;
case IP_IPPROTO_IPV6:
return IPMIP_TUNNELTYPE_IP6IP6;
default:
return IPMIP_TUNNELTYPE_NONE;
}
}
/*
*===========================================================================
* ipmip_util_tunnel_to_bsdname
*===========================================================================
* Description: Convert a tunnel index number to a BSD tunnel name
* Parameters: tunnel - Tunnel index
* Returns: Tunnel name
*
*/
IP_GLOBAL const char *
ipmip_util_tunnel_to_bsdname(Ip_u8 tunnel)
{
switch (tunnel)
{
case IPMIP_TUNNELTYPE_IP6IP6:
case IPMIP_TUNNELTYPE_IPIP:
return "gif";
case IPMIP_TUNNELTYPE_GRE6:
case IPMIP_TUNNELTYPE_GRE:
return "gre";
case IPMIP_TUNNELTYPE_MINENC:
return "gremin";
default:
return "unknown";
}
}
/*
*===========================================================================
* ipmip_util_tunnel_to_bsdname
*===========================================================================
* Description: Convert a tunnel index number to a BSD tunnel name
* Parameters: tunnel - Tunnel index
* Returns: Tunnel name
*
*/
IP_GLOBAL const char *
ipmip_util_tunnel_to_name(Ip_u8 tunnel)
{
switch (tunnel)
{
case IPMIP_TUNNELTYPE_IP6IP6:
return "ip6ip6";
case IPMIP_TUNNELTYPE_IPIP:
return "ipip";
case IPMIP_TUNNELTYPE_GRE6:
return "gre6";
case IPMIP_TUNNELTYPE_GRE:
return "gre";
case IPMIP_TUNNELTYPE_MINENC:
return "minenc";
default:
return "unknown";
}
}
#ifdef IPMIP_USE_INET
/*
*===========================================================================
* ipmip_util_inet
*===========================================================================
* Description: Parse an string to the subnet and prefix length it specifies.
* Parameters: addrstr - The address string
* addr - Where to store the address
* plen - The prefix length.
* Returns: IP_TRUE if successful.
*
*/
IP_GLOBAL Ip_bool
ipmip_util_inet(const char *addrstr,
Ip_u32 *addr,
Ip_u32 *plen)
{
char *a;
char *p = IP_NULL;
char *n;
char *buf = ipcom_strdup(addrstr);
if (buf == IP_NULL)
return IP_FALSE;
/* Get first token */
if ((a = ipcom_strtok_r(buf, " \t/-", &n)) == IP_NULL)
goto errout;
/* Get second token */
if (plen)
{
if ((p = ipcom_strtok_r(IP_NULL, " \t/", &n)) == IP_NULL)
{
*plen = 32;
}
else
{
int prefix = ipcom_atoi(p);
/* Sanity */
if (prefix < 0 || prefix > 32)
goto errout;
/* Store it */
*plen = (Ip_u8) prefix;
}
}
/* Convert address */
if (ipcom_inet_pton(IP_AF_INET, a, addr) != 1)
goto errout;
ipcom_free(buf);
return IP_TRUE;
errout:
ipcom_free(buf);
return IP_FALSE;
}
#endif
#ifdef IPMIP_USE_INET6
/*
*===========================================================================
* ipmip_util_inet6
*===========================================================================
* Description: Parse an string to the subnet and prefix length it specifies.
* Parameters: addrstr - The address string
* addr6 - Where to store the address
* plen - The prefix length.
* Returns: IP_TRUE if successful.
*
*/
IP_GLOBAL Ip_bool
ipmip_util_inet6(const char *addrstr,
struct Ip_in6_addr *addr6,
Ip_u8 *plen)
{
char *a;
char *p = IP_NULL;
char *n;
char *buf = ipcom_strdup(addrstr);
if (buf == IP_NULL)
return IP_FALSE;
/* Get first token */
if ((a = ipcom_strtok_r(buf, " \t/", &n)) == IP_NULL)
goto errout;
/* Get second token */
if (plen)
{
if ((p = ipcom_strtok_r(IP_NULL, " \t/", &n)) == IP_NULL)
{
*plen = 128;
}
else
{
int prefix = ipcom_atoi(p);
/* Sanity */
if (prefix < 0 || prefix > 128)
goto errout;
/* Store it */
*plen = (Ip_u8) prefix;
}
}
/* Convert address */
if (ipcom_inet_pton(IP_AF_INET6, a, addr6) != 1)
goto errout;
ipcom_free(buf);
return IP_TRUE;
errout:
ipcom_free(buf);
return IP_FALSE;
}
#endif
/*
*===========================================================================
* ipmip_util_inet6
*===========================================================================
* Description: Parse an string to the subnet and prefix length it specifies.
* Parameters: addrstr - The address string
* addr6 - Where to store the address
* plen - The prefix length.
* Returns: IP_TRUE if successful.
*
*/
IP_GLOBAL Ip_bool
ipmip_util_inetX(const char *addrstr,
Ip_u8 *domain,
union Ip_in_addr_union *addrX,
Ip_u8 *plen)
{
#ifdef IPMIP_USE_INET6
if (ipmip_util_inet6(addrstr, &addrX->in6, plen))
{
*domain = IP_AF_INET6;
return IP_TRUE;
}
#endif
#ifdef IPMIP_USE_INET
{
Ip_u32 plen32;
if (ipmip_util_inet(addrstr, &addrX->in.s_addr, &plen32))
{
*domain = IP_AF_INET;
if (plen)
*plen = (Ip_u8)plen32;
return IP_TRUE;
}
}
#endif
return IP_FALSE;
}
/*
*===========================================================================
* ipmip_util_inet6
*===========================================================================
* Description: Parse an string to the subnet and prefix length it specifies.
* Parameters: addrstr - The address string
* addr6 - Where to store the address
* plen - The prefix length.
* Returns: IP_TRUE if successful.
*
*/
IP_GLOBAL Ip_bool
ipmip_util_sockaddrX(const char *addrstr,
union Ip_sockaddr_union *unX)
{
char *buf = ipcom_strdup(addrstr);
char *ntok;
char *addr;
char *n;
Ip_u16 port = 0;
ipcom_memset(unX, 0, sizeof(*unX));
if (buf == IP_NULL)
return IP_FALSE;
if ((addr = ipcom_strtok_r(buf, " \t", &n)) == IP_NULL)
{
ipcom_free(buf);
return IP_FALSE;
}
if ((ntok = ipcom_strtok_r(IP_NULL, " \t", &n)) != IP_NULL)
port = (Ip_u16)ipcom_strtoul(ntok, IP_NULL, 0);
#ifdef IPMIP_USE_INET6
if (ipcom_getsockaddrbyaddr(IP_AF_INET6, addr, &unX->sa) == 0)
{
ipcom_free(buf);
unX->sin6.sin6_port = ip_htons(port);
return IP_TRUE;
}
#endif
#ifdef IPMIP_USE_INET
if (ipcom_getsockaddrbyaddr(IP_AF_INET, addr, &unX->sa) == 0)
{
ipcom_free(buf);
unX->sin.sin_port = ip_htons(port);
return IP_TRUE;
}
#endif
ipcom_free(buf);
return IP_FALSE;
}
/*
*===========================================================================
* ipmip_util_duplicate
*===========================================================================
* Description: Create a duplicate buffer and store in ptr; if ptr is already
* set, free it.
* Parameters: ptr - [IN/OUT] Set pointer will be freed, and newly
* allocated will be set.
* value - Value to copy
* sz - Size of value
* Returns:
*
*/
IP_GLOBAL void
ipmip_util_duplicate(void **ptr,
void *value,
Ip_size_t sz)
{
void * tmp = ipcom_malloc(sz);
if(IP_NULL != tmp)
{
if (*ptr)
ipcom_free(*ptr);
*ptr = tmp;
ipcom_memcpy(*ptr, value, sz);
}
}
/*
*===========================================================================
* ipmip_util_ioctl
*===========================================================================
* Description: Do an ioctl
* Parameters: ioreq - The ioctl
* argp - Value to provide
* Returns: The return value.
*
*/
IP_GLOBAL int
ipmip_util_ioctl(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
unsigned long ioreq,
void *argp)
{
IPMIP_UNUSED_PARAMETER(proc);
return ipcom_socketioctl(ctx->fd_ioctl, ioreq, argp);
}
/*
*===========================================================================
* ipmip4_util_create_mask
*===========================================================================
* Description: Creates a mask which contains 'netbits' number of '1' bits
* staring with the most significant bit.
* Parameters: mask - Mask buffer.
* netbits - Number of bits.
* Returns:
*
*/
IP_GLOBAL void
ipmip_util_create_mask(Ip_u8 *mask,
int netbits)
{
#if 1
int i;
int j;
for (i = 0; i < netbits / 8; i++)
mask[i] = 0xff;
for (j = 0; j < netbits % 8; j++)
IP_BIT_SET(mask[i], 0x80 >> j);
#else
int i;
for (i = 0; i < netbits; i++)
{
IP_BIT_SET(((Ip_u16*) mask)[i / 16], ip_htons(0x8000 >> (i % 16)));
}
#endif
}
/*
*===========================================================================
* ipmip_util_cmp_bitarray
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_bool
ipmip_util_cmp_bitarray(void *bitarray1,
void *bitarray2,
int bits)
{
int blen;
int plen;
/* Convert to bytes. */
plen = bits >> 3;
/* Any bits left in the next byte that we need to match? */
blen = bits & 7;
/* Check the whole bytes. */
if (ipcom_memcmp(bitarray1, bitarray2, plen) != 0)
return IP_FALSE;
if (blen)
{
/* Create a usable mask */
blen = (Ip_u8) (0xff00 >> blen);
/* Match */
return (((Ip_u8 *)bitarray1)[plen] & blen) == (((Ip_u8 *)bitarray2)[plen] & blen);
}
/* Match? */
return IP_TRUE;
}
/*
*===========================================================================
* ipmip_util_hash_foreach
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL void
ipmip_util_hash_foreach(Ipmip_context_t *ctx,
Ipmip_proc_t *proc,
Ipcom_hash *hash,
Ipmip_util_hash_foreach_t func,
void *arg1,
void *arg2)
{
struct Ipmip_util_cbinfo cbinfo;
cbinfo.arg1 = arg1;
cbinfo.arg2 = arg2;
cbinfo.ctx = ctx;
cbinfo.func = func;
cbinfo.proc = proc;
ipcom_hash_for_each(hash,
(Ipcom_hash_foreach_cb_func) ipmip_util_hash_foreach_cb,
&cbinfo);
}
IP_GLOBAL void
ipmip_util_hash_free(Ipcom_hash *hash,
Ipmip_util_hash_free_t func)
{
struct Ipmip_util_freeinfo cbinfo;
cbinfo.func = func;
cbinfo.hash = hash;
ipcom_hash_for_each(hash,
(Ipcom_hash_foreach_cb_func) ipmip_util_hash_free_cb,
&cbinfo);
}
#define IPMIP_UTIL_STRLIST_SPACE " \t,;"
/*
*===========================================================================
* ipmip_sysvar_explode
*===========================================================================
* Description: Parses a command string to the traditional argc and argv
* arguments.
* Parameters:
* Returns:
*/
IP_GLOBAL Ip_u8 *
ipmip_util_explode(const char *arg_str)
{
int pos = 0;
int arg_str_len;
Ip_bool endreq = IP_FALSE;
Ip_bool escaped = IP_FALSE;
char *endstr = IP_NULL;
Ip_u8 *cptr = IP_NULL;
Ip_u8 *sptr = IP_NULL;
Ip_u8 *nptr = IP_NULL;
Ip_u8 *dblock;
enum { skipping_space, searching_end_of_arg } state;
state = skipping_space;
arg_str_len = ipcom_strlen(arg_str);
endstr = IPMIP_UTIL_STRLIST_SPACE;
dblock = ipcom_malloc((arg_str_len + 1) * 2 + 1);
if(dblock == IP_NULL)
return IP_NULL;
nptr = dblock;
sptr = cptr = dblock + 1;
*nptr = 0;
while(pos < arg_str_len)
{
switch(state)
{
case skipping_space:
endstr = IPMIP_UTIL_STRLIST_SPACE;
if (!escaped)
{
if(ipcom_strchr(IPMIP_UTIL_STRLIST_SPACE, arg_str[pos]))
break;
if(arg_str[pos] == '\'')
{
endstr = "\'";
endreq = IP_TRUE;
pos++;
}
else if(arg_str[pos] == '"')
{
endstr = "\"";
endreq = IP_TRUE;
pos++;
}
else if (arg_str[pos] == '\\')
escaped = IP_TRUE;
}
#if 0
else
/* We've processed the escaped character */
escaped = IP_FALSE;
#endif
/* Start building the argument */
sptr = cptr++;
*sptr = 1;
(*nptr)++;
/* Unless escaped; advance past the first character */
if (!escaped)
{
*cptr++ = (Ip_u8)arg_str[pos];
(*sptr)++;
}
state = searching_end_of_arg;
break;
case searching_end_of_arg:
if (!escaped)
{
if (arg_str[pos] == '\\')
escaped = IP_TRUE;
else if(ipcom_strchr(endstr, arg_str[pos]))
{
state = skipping_space;
*cptr++ = '\0';
(*sptr)++;
endreq = IP_FALSE;
}
else
{
*cptr++ = (Ip_u8)arg_str[pos];
(*sptr)++;
}
}
else
{
escaped = IP_FALSE;
*cptr++ = (Ip_u8)arg_str[pos];
(*sptr)++;
}
break;
default:
IP_PANIC();
break;
}
pos++;
}
if(state == searching_end_of_arg && endreq == IP_TRUE)
goto err;
else
{
*cptr++ = '\0';
(*sptr)++;
}
/* Zero termination */
*cptr++ = 0;
return dblock;
err:
if(dblock != IP_NULL)
ipcom_free(dblock);
return IP_NULL;
}
/*
*===========================================================================
* ipmip_sysvar_explode
*===========================================================================
* Description: Parses a command string to the traditional argc and argv
* arguments.
* Parameters:
* Returns:
*/
IP_GLOBAL char **
ipmip_util_strarr(const char *buf, Ip_size_t *numelem)
{
Ip_u8 *dblock = ipmip_util_explode(buf);
if (dblock)
{
Ip_u8 *sptr;
Ip_size_t i;
Ip_u8 *sbuf;
char **ptrarr;
if (*dblock == 0)
{
ipcom_free(dblock);
return IP_NULL;
}
for (i = 0, sptr = dblock + 1; *sptr != 0; sptr += *sptr)
i += *sptr;
sbuf = ipcom_calloc(1, (sizeof(char **) * (*dblock + 1)) + i);
ptrarr = (char **)sbuf;
sbuf += sizeof(char **) * (*dblock + 1);
/* OK */
for (i = 0, sptr = dblock + 1; *sptr != 0; sptr += *sptr, i++)
{
ptrarr[i] = (char *)sbuf;
ipcom_memcpy(ptrarr[i], sptr + 1, *sptr - 1);
sbuf += *sptr - 1;
}
ipcom_free(dblock);
if (numelem)
*numelem = i;
return ptrarr;
}
return IP_NULL;
}
/*
*===========================================================================
* ipmip_util_strnncmp
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_bool
ipmip_util_strnncmp(const char *str1,
Ip_size_t str1_len,
const char *str2,
Ip_size_t str2_len)
{
str1_len = ipmip_util_strnlen(str1, str1_len);
str2_len = ipmip_util_strnlen(str2, str2_len);
if (str1_len != str2_len)
return IP_FALSE;
return ipcom_strncmp(str1, str2, str1_len) == 0;
}
/*
*===========================================================================
* ipmip_util_strnncmp
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_size_t
ipmip_util_strstrip0(const char *str1,
Ip_size_t str1_len)
{
while (str1_len > 0)
{
if (str1[str1_len - 1] == '\0')
str1_len--;
else
break;
}
/* Return the stripped value */
return str1_len;
}
/*
*===========================================================================
* ipmip_util_strnncmp
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_bool
ipmip_util_strnnmatch(const char *str1,
Ip_size_t str1_len,
const char *str2,
Ip_size_t str2_len)
{
str1_len = ipmip_util_strnlen(str1, str1_len);
str2_len = ipmip_util_strnlen(str2, str2_len);
/* Exact match? */
if (str1_len == str2_len && ipcom_strncmp(str1, str2, str1_len) == 0)
return IP_TRUE;
if (str1[0] == '@' || str1[0] == '*')
{
/* Match tail */
str1 = &str1[1];
str1_len--;
if (str2_len >= str1_len)
{
if (ipcom_strncmp(str1, &str2[str2_len - str1_len], str1_len) == 0)
return IP_TRUE;
}
}
if (str2[0] == '@' || str2[0] == '*')
{
str2 = &str2[1];
str2_len--;
if (str1_len >= str2_len)
{
if (ipcom_strncmp(str2, &str1[str1_len - str2_len], str2_len) == 0)
return IP_TRUE;
}
}
return IP_FALSE;
}
/*
*===========================================================================
* ipmip_util_hdrprintf
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL void
ipmip_util_hdrprintf(Ipmip_proc_t *proc,
int tabs,
const char *header,
Ip_size_t hdr_size,
const char *format,
...)
{
va_list ap;
ipmip_util_print_tabs(tabs);
ipmip_util_print_hdr(proc, header? header : "", hdr_size, ":");
va_start(ap, format);
ipcom_vsnprintf(proc->ntop.ntop_pbuf, sizeof(proc->ntop.ntop_pbuf), format , ap);
ipcom_printf(proc->ntop.ntop_pbuf);
va_end(ap);
}
/*
*===========================================================================
* ipmip_util_identprintf
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL void
ipmip_util_identprintf(Ipmip_proc_t *proc,
int tabs,
const char *format,
...)
{
va_list ap;
va_start(ap, format);
ipcom_vsnprintf(proc->ntop.ntop_pbuf, sizeof(proc->ntop.ntop_pbuf), format , ap);
ipmip_util_bidentprintf(proc, tabs, proc->ntop.ntop_pbuf);
va_end(ap);
}
/*
*===========================================================================
* ipmip_util_hdrprintf
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL void
ipmip_util_cmdprintf(Ipmip_proc_t *proc,
int tabs,
const char *cmd,
const char *format,
...)
{
va_list ap;
ipmip_util_print_tabs(tabs);
ipcom_printf("%s"IP_LF, cmd);
va_start(ap, format);
ipcom_vsnprintf(proc->ntop.ntop_pbuf, sizeof(proc->ntop.ntop_pbuf), format , ap);
va_end(ap);
if (ipcom_strstr(proc->ntop.ntop_pbuf, IP_LF))
{
ipmip_util_bidentprintf(proc, tabs + 1, proc->ntop.ntop_pbuf);
ipcom_printf(IP_LF);
}
else
{
ipmip_util_print_tabs(tabs + 1);
ipcom_printf("%s"IP_LF, proc->ntop.ntop_pbuf);
}
}
/*
*===========================================================================
* ipmip_util_bool_safe
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL Ip_bool
ipmip_util_bool_safe(const Ip_bool *bptr)
{
Ip_bool sbool;
ipcom_memcpy(&sbool, bptr, sizeof(sbool));
return sbool;
}
/*
*===========================================================================
* ipmip_util_syslog_priority
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL int
ipmip_util_syslog_priority(const char *val)
{
/**/
return ipmip_sysvar_cmd_str_to_key(ipmip_util_sysvar_ops, val);
}
/*
*===========================================================================
* ipmip_util_syslog_priority_name
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_GLOBAL const char *
ipmip_util_syslog_priority_name(Ip_u32 val)
{
int i;
for (i = 0; ipmip_util_sysvar_ops[i].str != 0; i++)
{
if (ipmip_util_sysvar_ops[i].key == (signed)val)
return ipmip_util_sysvar_ops[i].str;
}
return "Unknown";
}
IP_GLOBAL Ip_u32
ipmip_util_route_table_alloc(struct Ipmip_context *ctx,
struct Ipmip_proc *proc)
{
struct Ip_sioc_route_table iftable;
ipcom_memset(&iftable, 0, sizeof(iftable));
iftable.table = IPCOM_ROUTE_TABLE_ANY;
iftable.vr = ctx->vr;
(void)ipmip_util_ioctl(ctx, proc, IP_SIOCADDROUTETAB, &iftable);
return iftable.table;
}
IP_GLOBAL void
ipmip_util_route_table_free(struct Ipmip_context *ctx,
struct Ipmip_proc *proc,
Ip_u32 table)
{
struct Ip_sioc_route_table iftable;
ipcom_memset(&iftable, 0, sizeof(iftable));
iftable.table = table;
iftable.vr = ctx->vr;
/* Delete the route tables */
(void)ipmip_util_ioctl(ctx, proc, IP_SIOCDELROUTETAB, &iftable);
}
IP_GLOBAL Ip_u8 *
ipmip_util_values_to_hexarray(const char *value,
Ip_size_t *size)
{
char **values = ipmip_util_strarr(value, IP_NULL);
Ip_u8 *ptrarr;
int i;
Ip_size_t sz = 0;
if (values == IP_NULL)
return IP_NULL;
for (i = 0; values[i] != IP_NULL; i++)
{
Ip_size_t vlen = ipcom_strlen(values[i]);
if (ipcom_strncasecmp(values[i], "0x", 2) == 0)
{
vlen -= 2;
vlen = (vlen + 1) / 2;
if (vlen == 3)
vlen++;
if (vlen > 4)
{
ipcom_free(values);
return IP_NULL;
}
}
sz += vlen;
}
ptrarr = ipcom_malloc(sz);
if (ptrarr == IP_NULL)
{
ipcom_free(values);
return IP_NULL;
}
for (sz = 0, i = 0; values[i] != IP_NULL; i++)
{
Ip_size_t vlen = ipcom_strlen(values[i]);
if (ipcom_strncasecmp(values[i], "0x", 2) == 0)
{
Ip_u32 v = ipcom_strtoul(values[i], IP_NULL, 0);
vlen -= 2;
vlen = (vlen + 1) / 2;
switch (vlen)
{
case 1:
ptrarr[sz] = (Ip_u8)v;
break;
case 2:
IP_SET_HTONS(&ptrarr[sz], (Ip_u16)v);
break;
/* coverity[unterminated_case] */
case 3:
vlen++;
/* this is an intentional fall through to the next case */
case 4:
IP_SET_HTONL(&ptrarr[sz], (Ip_u32)v);
break;
}
}
else
{
/* Copy */
ipcom_memcpy(&ptrarr[sz], values[i], vlen);
}
sz += vlen;
}
*size = sz;
ipcom_free(values);
return ptrarr;
}
IP_GLOBAL Ip_u64
ipmip_util_bswap64(Ip_u64 *u64)
{
Ip_u64 val;
ipcom_memcpy(&val, u64, sizeof(val));
return IPMIP_BSWAP64(val);
}
IP_GLOBAL Ip_time_t
ipmip_util_safe_time_t(const Ip_time_t *tt)
{
Ip_time_t ntt;
ipcom_memcpy(&ntt, tt, sizeof(ntt));
return ntt;
}
IP_GLOBAL Ip_u64
ipmip_util_safe_u64(const Ip_u64 *tt)
{
Ip_u64 ntt;
ipcom_memcpy(&ntt, tt, sizeof(ntt));
return ntt;
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/