1496 lines
38 KiB
C
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
|
|
****************************************************************************
|
|
*/
|