2568 lines
70 KiB
C
2568 lines
70 KiB
C
/*
|
|
******************************************************************************
|
|
* SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_RCPL8_2024030303 $ $RCSfile: ipike_util.c,v $ $Revision: 1.82.10.12 $
|
|
* $Source: /home/interpeak/CVSRoot/ipike/src/ipike_util.c,v $
|
|
* $Author: jren $ $Date: 2023-10-20 05:56:11 $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Kenneth Jonsson <kenneth@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/* Helper functions not directly releated to IKE */
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
#include "ipike_config.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#include "ipike_h.h"
|
|
#include "ipike_util.h"
|
|
#include "ipike_attributes.h"
|
|
#include "ipike_configuration.h"
|
|
#include "ipike_configuration_parse.h"
|
|
|
|
#include <ipcom_os.h>
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_syslog.h>
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_inet_pton
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC int
|
|
ipike_inet_pton(int family, IP_CONST char *strptr, void *addrptr);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_get_first_if_name
|
|
*===========================================================================
|
|
* Description: Get first available interface name.
|
|
* Parameters: name - buffer that will receive the null terminated interface
|
|
* name.
|
|
* size - size of name buffer.
|
|
* Returns: IP_TRUE if success (else IP_FALSE)
|
|
*/
|
|
IP_STATIC Ip_bool
|
|
ipike_get_first_if_name(char *name, Ip_u32 size);
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_add_delete_ipv4_address
|
|
*===========================================================================
|
|
* Description: Add/Delete IPv4 address from interface.
|
|
* Parameters: add - Set to IP_TRUE for add address (IP_FALSE for delete)
|
|
* ifname - Interface name, set to IP_NULL to get first available
|
|
* interface.
|
|
* addr - The ip address to set
|
|
* netmask - The ip netmask to set
|
|
* Returns: IPIKE_SUCCESS, IPIKE_FAILED
|
|
*/
|
|
#ifdef IPCOM_USE_INET
|
|
IP_STATIC Ipike_error
|
|
ipike_add_delete_ipv4_address(
|
|
Ip_bool add,
|
|
const char *ifname,
|
|
struct Ip_sockaddr_in *addr,
|
|
struct Ip_sockaddr_in *netmask);
|
|
#endif /* IPCOM_USE_INET */
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_add_delete_ipv6_address
|
|
*===========================================================================
|
|
* Description: Add/Delete IPv6 address from interface.
|
|
* Parameters: add - Set to IP_TRUE for add address (IP_FALSE for delete)
|
|
* ifname - Interface name, set to IP_NULL to get first available
|
|
* interface.
|
|
* addr - The ip address to set
|
|
* netmask - The ip netmask to set
|
|
* Returns: IPIKE_SUCCESS, IPIKE_FAILED
|
|
*/
|
|
#ifdef IPCOM_USE_INET6
|
|
IP_STATIC Ipike_error
|
|
ipike_add_delete_ipv6_address(
|
|
Ip_bool add,
|
|
const char *ifname,
|
|
struct Ip_sockaddr_in6 *addr,
|
|
struct Ip_sockaddr_in6 *netmask);
|
|
#endif /* IPCOM_USE_INET6 */
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 LOCAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_inet_pton
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC int
|
|
ipike_inet_pton(int family, IP_CONST char *strptr, void *addrptr)
|
|
{
|
|
char strbuf[128];
|
|
|
|
ipcom_strncpy(strbuf, strptr,127);
|
|
|
|
#ifdef IPCOM_USE_INET
|
|
/* Remove trailing ':' in address */
|
|
if (family == IP_AF_INET)
|
|
{
|
|
char *delim;
|
|
|
|
delim = ipcom_strrchr(strbuf, ':');
|
|
if (delim != IP_NULL)
|
|
*delim = '\0';
|
|
}
|
|
#endif /* IPCOM_USE_INET */
|
|
|
|
return ipcom_inet_pton(family, strbuf, addrptr);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_get_first_if_name
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ip_bool
|
|
ipike_get_first_if_name(char *name, Ip_u32 size)
|
|
{
|
|
struct Ip_if_nameindex *ni;
|
|
int i;
|
|
|
|
name[0] = 0;
|
|
if ((ni = ipcom_if_nameindex()) == IP_NULL)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_get_first_if_name: failed to get interface list");
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; (ni[i].if_name != IP_NULL) && (name[0] == 0); i++)
|
|
{
|
|
if ((ipcom_strcmp(ni[i].if_name, "lo0") == 0) ||
|
|
(ipcom_strcmp(ni[i].if_name, "lo") == 0))
|
|
continue;
|
|
if (size <= (Ip_u32)ipcom_strlen(ni[i].if_name))
|
|
continue;
|
|
ipcom_strcpy(name, ni[i].if_name);
|
|
}
|
|
ipcom_if_freenameindex(ni);
|
|
}
|
|
|
|
return (name[0] != 0);
|
|
}
|
|
|
|
#ifdef IPCOM_USE_INET
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_add_delete_ipv4_address
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ipike_error
|
|
ipike_add_delete_ipv4_address(
|
|
Ip_bool add,
|
|
const char *ifname,
|
|
struct Ip_sockaddr_in *addr,
|
|
struct Ip_sockaddr_in *netmask)
|
|
{
|
|
Ipike_error err = IPIKE_SUCCESS;
|
|
Ip_fd fd = IP_INVALID_SOCKET;
|
|
struct Ip_ifaliasreq ifal;
|
|
struct Ip_sockaddr_in *in;
|
|
unsigned long request;
|
|
|
|
ipcom_memset(&ifal, 0, sizeof(ifal));
|
|
if (ifname == IP_NULL)
|
|
{
|
|
if (!ipike_get_first_if_name(ifal.ifra_name, sizeof(ifal.ifra_name)))
|
|
ifal.ifra_name[0] = 0;
|
|
}
|
|
else
|
|
{
|
|
if (ipcom_strlen(ifname) < sizeof(ifal.ifra_name))
|
|
ipcom_strcpy(ifal.ifra_name, ifname);
|
|
}
|
|
if ((addr == IP_NULL) || (ifal.ifra_name[0] == 0))
|
|
{
|
|
IPCOM_LOG0(DEBUG, "ipike_add_ipv4_address: bad arguments");
|
|
err = IPIKE_FAILED;
|
|
}
|
|
else
|
|
{
|
|
fd = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, 0);
|
|
if (fd == IP_INVALID_SOCKET)
|
|
{
|
|
IPCOM_LOG0(DEBUG, "ipike_add_ipv4_address: failed to open socket");
|
|
err = IPIKE_FAILED;
|
|
}
|
|
else
|
|
{
|
|
in = (struct Ip_sockaddr_in *) &ifal.ifra_addr;
|
|
in->sin_addr = addr->sin_addr;
|
|
in->sin_family = addr->sin_family;
|
|
IPCOM_SA_LEN_SET(in, IPCOM_SA_LEN_GET(addr));
|
|
in = (struct Ip_sockaddr_in *) &ifal.ifra_mask;
|
|
if ((netmask != IP_NULL) && (netmask->sin_family == IP_AF_INET))
|
|
in->sin_addr = netmask->sin_addr;
|
|
else
|
|
ipcom_memset(&in->sin_addr, 0xff, sizeof(in->sin_addr));
|
|
|
|
request = ipike.dynamic_ip_homeaddr ? IP_SIOCAHOMEADDR : IP_SIOCAIFADDR;
|
|
if (ipcom_socketioctl(fd, add ? request : IP_SIOCDIFADDR, &ifal) < 0)
|
|
{
|
|
IPCOM_LOG3(DEBUG, "ipike_add_ipv4_address: set address failed <if=%s, addr=%s> (%d)",
|
|
ifal.ifra_name,
|
|
ipike_addr_to_str((union Ip_sockaddr_union *)addr),
|
|
ipcom_errno);
|
|
err = IPIKE_FAILED;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fd != IP_INVALID_SOCKET)
|
|
(void)ipcom_socketclose(fd);
|
|
|
|
return err;
|
|
}
|
|
|
|
#endif /* IPCOM_USE_INET */
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_add_delete_ipv6_address
|
|
*===========================================================================
|
|
*/
|
|
#ifdef IPCOM_USE_INET6
|
|
IP_STATIC Ipike_error
|
|
ipike_add_delete_ipv6_address(
|
|
Ip_bool add,
|
|
const char *ifname,
|
|
struct Ip_sockaddr_in6 *addr,
|
|
struct Ip_sockaddr_in6 *netmask)
|
|
{
|
|
Ipike_error err = IPIKE_SUCCESS;
|
|
Ip_fd fd = IP_INVALID_SOCKET;
|
|
struct Ip_in6_aliasreq ifareq;
|
|
|
|
ipcom_memset(&ifareq, 0, sizeof(ifareq));
|
|
if (ifname == IP_NULL)
|
|
{
|
|
if (!ipike_get_first_if_name(ifareq.ifra_name, sizeof(ifareq.ifra_name)))
|
|
ifareq.ifra_name[0] = 0;
|
|
}
|
|
else
|
|
{
|
|
if (ipcom_strlen(ifname) < sizeof(ifareq.ifra_name))
|
|
ipcom_strcpy(ifareq.ifra_name, ifname);
|
|
}
|
|
if ((addr == IP_NULL) || (ifareq.ifra_name[0] == 0))
|
|
{
|
|
IPCOM_LOG0(DEBUG, "ipike_add_ipv6_address: bad arguments");
|
|
err = IPIKE_FAILED;
|
|
}
|
|
else
|
|
{
|
|
fd = ipcom_socket(IP_AF_INET6, IP_SOCK_DGRAM, 0);
|
|
if (fd == IP_INVALID_SOCKET)
|
|
{
|
|
IPCOM_LOG0(DEBUG, "ipike_add_ipv6_address: failed to open socket");
|
|
err = IPIKE_FAILED;
|
|
}
|
|
else
|
|
{
|
|
ifareq.ifra_addr.sin6_family = IP_AF_INET6;
|
|
IPCOM_SA_LEN_SET(&ifareq.ifra_addr, sizeof(struct Ip_sockaddr_in6));
|
|
ifareq.ifra_addr.sin6_addr = addr->sin6_addr;
|
|
ifareq.ifra_addr.sin6_scope_id = 0;
|
|
|
|
if (add)
|
|
{
|
|
ifareq.ifra_prefixmask.sin6_family = IP_AF_INET6;
|
|
IPCOM_SA_LEN_SET(&ifareq.ifra_prefixmask, sizeof(struct Ip_sockaddr_in6));
|
|
if ((netmask != IP_NULL) && (netmask->sin6_family == IP_AF_INET6))
|
|
ifareq.ifra_prefixmask.sin6_addr = netmask->sin6_addr;
|
|
else
|
|
ipcom_memset(&ifareq.ifra_prefixmask.sin6_addr, 0xff, sizeof(ifareq.ifra_prefixmask.sin6_addr));
|
|
|
|
ifareq.ifra_lifetime.ia6t_preferred = (Ip_time_t)IPCOM_ADDR_INFINITE;
|
|
ifareq.ifra_lifetime.ia6t_expire = (Ip_time_t)IPCOM_ADDR_INFINITE;
|
|
|
|
if (ipike.dynamic_ip_homeaddr)
|
|
ifareq.ifra_flags |= IP_IN6_IFF_HOMEADDRESS;
|
|
if (ipcom_socketioctl(fd, IP_SIOCAIFADDR_IN6, &ifareq) < 0)
|
|
{
|
|
IPCOM_LOG0(DEBUG, "ipike_add_ipv6_address: failed to add address");
|
|
err = IPIKE_FAILED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ipcom_socketioctl(fd, IP_SIOCDIFADDR_IN6, &ifareq) < 0)
|
|
{
|
|
IPCOM_LOG0(DEBUG, "ipike_add_ipv6_address: failed to delete address");
|
|
err = IPIKE_FAILED;
|
|
}
|
|
}
|
|
}
|
|
if (fd != IP_INVALID_SOCKET)
|
|
(void)ipcom_socketclose(fd);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* IPCOM_USE_INET6 */
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_are_values_equal
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipike_are_values_equal(const Ipike_value *val1, const Ipike_value *val2)
|
|
{
|
|
if (IP_NULL == val1 || IP_NULL == val2)
|
|
return IP_FALSE;
|
|
if (val1->len != val2->len)
|
|
return IP_FALSE;
|
|
return 0 == ipcom_memcmp(val1->value, val2->value, val1->len);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_are_cookies_equal
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipike_are_cookies_equal(const Ip_u8 cookie1[], const Ip_u8 cookie2[])
|
|
{
|
|
if (ipike_is_zero_cookie(cookie1) || ipike_is_zero_cookie(cookie2))
|
|
return IP_TRUE;
|
|
return 0 == ipcom_memcmp(cookie1, cookie2, IPIKE_ISAKMP_COOKIE_SIZE);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_set_value
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_set_value(Ipike_value *destination, const Ipike_value *source)
|
|
{
|
|
destination->value = IP_NULL;
|
|
destination->len = 0;
|
|
|
|
return ipike_set_data(destination, source->value, source->len);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_cpy_value
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_cpy_value(Ipike_value *destination, const Ipike_value *source)
|
|
{
|
|
IPIKE_FREEP(destination->value);
|
|
|
|
return ipike_set_value(destination, source);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_swap_value
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_swap_value(Ipike_value *v1, Ipike_value *v2)
|
|
{
|
|
Ipike_value tmp;
|
|
|
|
tmp.len = v1->len;
|
|
tmp.value = v1->value;
|
|
|
|
v1->len = v2->len;
|
|
v1->value = v2->value;
|
|
|
|
v2->len = tmp.len;
|
|
v2->value = tmp.value;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_set_data
|
|
*===========================================================================
|
|
*/
|
|
#ifdef IPCOM_USE_DMALLOC
|
|
IP_GLOBAL Ipike_error
|
|
ipike_set_data_debug(Ipike_value *destination, const void *data, Ip_size_t len, const char *file, const char *function, Ip_u32 line)
|
|
#else
|
|
IP_GLOBAL Ipike_error
|
|
ipike_set_data(Ipike_value *destination, const void* data, Ip_size_t len)
|
|
#endif
|
|
{
|
|
destination->value = IP_NULL;
|
|
destination->len = 0;
|
|
|
|
if (data == IP_NULL || len == 0)
|
|
return IPIKE_SUCCESS;
|
|
|
|
#ifdef IPCOM_USE_DMALLOC
|
|
destination->value = ipcom_dmalloc(len, file, function, line);
|
|
#else
|
|
destination->value = ipcom_malloc(len);
|
|
#endif
|
|
if (destination->value == IP_NULL)
|
|
{
|
|
IP_PANIC();
|
|
return IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
|
|
ipcom_memcpy(destination->value, data, len);
|
|
destination->len = len;
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_cpy_data
|
|
*===========================================================================
|
|
*/
|
|
#ifdef IPCOM_USE_DMALLOC
|
|
IP_GLOBAL Ipike_error
|
|
ipike_cpy_data_debug(Ipike_value *destination, const void *data, Ip_size_t len, const char *file, const char *function, Ip_u32 line)
|
|
#else
|
|
IP_GLOBAL Ipike_error
|
|
ipike_cpy_data(Ipike_value *destination, const void *data, Ip_size_t len)
|
|
#endif
|
|
{
|
|
IPIKE_FREEP(destination->value);
|
|
|
|
#ifdef IPCOM_USE_DMALLOC
|
|
return ipike_set_data_debug(destination, data, len, file, function, line);
|
|
#else
|
|
return ipike_set_data(destination, data, len);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_appende_value
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_append_value(Ipike_value* destination, const Ipike_value* source)
|
|
{
|
|
return ipike_append_data(destination, source->value, source->len);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_append_data
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_append_data(Ipike_value* destination, const void* src_data, Ip_size_t src_len)
|
|
{
|
|
if( (src_data == IP_NULL) || (src_len == 0))
|
|
return IPIKE_SUCCESS;
|
|
|
|
destination->value = ipcom_realloc(destination->value, destination->len + src_len);
|
|
if (IP_NULL == destination->value)
|
|
{
|
|
IP_PANIC();
|
|
return IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
|
|
ipcom_memcpy(destination->value+destination->len, src_data, src_len);
|
|
destination->len += src_len;
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_is_zero_cookie
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipike_is_zero_cookie(const Ip_u8 cookie[])
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < IPIKE_ISAKMP_COOKIE_SIZE; i++)
|
|
if (0 != cookie[i])
|
|
return IP_FALSE;
|
|
return IP_TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_cookie_to_string
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL const char *
|
|
ipike_cookie_to_string(const Ip_u8 cookie[])
|
|
{
|
|
static char buf[20] = { '0', 'x' };
|
|
int i, j;
|
|
int nibble;
|
|
|
|
for (i = 0; i < IPIKE_ISAKMP_COOKIE_SIZE; i++)
|
|
for (j = 1; j >= 0; j--)
|
|
{
|
|
nibble = (cookie[i] >> (j * 4)) & 0x0F;
|
|
buf[2 + i * 2 + (1 - j)] = (char)
|
|
(nibble + (char) (nibble < 10 ? '0' : (char) ('a' - 10)));
|
|
}
|
|
buf[2 + 2 * i] = '\0';
|
|
|
|
return buf;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_memory_to_string
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL char *
|
|
ipike_memory_to_string(const Ip_u8 *ptr, Ip_size_t size, Ip_u8 alignment)
|
|
{
|
|
const Ip_u32 MAX_SIZE = 256;
|
|
static const char hex_char[] = "0123456789abcdef";
|
|
static const unsigned int byte_per_row = 32;
|
|
char* buf;
|
|
Ip_size_t row_size;
|
|
Ip_size_t i, j, k = 0;
|
|
Ip_size_t ws_per_row;
|
|
Ip_size_t full_rows, blr;
|
|
Ip_bool is_cut = IP_FALSE;
|
|
|
|
if (size > MAX_SIZE)
|
|
{
|
|
size = MAX_SIZE;
|
|
is_cut = IP_TRUE;
|
|
}
|
|
ws_per_row = byte_per_row / alignment;
|
|
row_size = 2 * byte_per_row + ws_per_row;
|
|
full_rows = size / byte_per_row;
|
|
blr = size % byte_per_row;
|
|
|
|
buf = ipcom_malloc(full_rows * row_size + 2 * blr + blr / alignment + 1 + 3);
|
|
if (IP_NULL == buf)
|
|
return IP_NULL;
|
|
|
|
for (i = 0; i <= full_rows; i++)
|
|
{
|
|
k = 0;
|
|
for (j = 0; j < (i == full_rows ? blr : byte_per_row); j++)
|
|
{
|
|
if (j != 0 && j % alignment == 0)
|
|
buf[i * row_size + 2 * j + k++] = ' ';
|
|
buf[i * row_size + 2 * j + k] =
|
|
hex_char[ptr[i * byte_per_row + j] >> 4];
|
|
buf[i * row_size + 2 * j + k + 1] =
|
|
hex_char[ptr[i * byte_per_row + j] & 0x0F];
|
|
}
|
|
buf[i * row_size + 2 * j + k] = '\n';
|
|
}
|
|
buf[full_rows * row_size + 2 * blr + k] = '\0';
|
|
if (is_cut)
|
|
ipcom_strcat(buf, "...");
|
|
|
|
return buf;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_print_memory
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_print_memory(Ip_u32 priority, const char *prefix, const Ip_u8 *data, Ip_size_t len)
|
|
{
|
|
char *hex_mem;
|
|
|
|
if (data == IP_NULL)
|
|
{
|
|
IPCOM_LOG1(ERR, "%sNULL-data error", prefix);
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
hex_mem = ipike_memory_to_string(data, len, 4);
|
|
if (hex_mem == IP_NULL)
|
|
{
|
|
IP_PANIC();
|
|
return IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
|
|
/* Make sure fit into syslog buffer */
|
|
if ((ipcom_strlen(hex_mem) + ipcom_strlen(prefix)) >= IPCOM_SYSLOG_MAX_SIZE)
|
|
{
|
|
len = IPCOM_SYSLOG_MAX_SIZE - ipcom_strlen(prefix);
|
|
hex_mem[len-4] = '.';
|
|
hex_mem[len-3] = '.';
|
|
hex_mem[len-2] = '.';
|
|
hex_mem[len-1] = 0;
|
|
}
|
|
|
|
switch (priority)
|
|
{
|
|
case IPCOM_LOG_EMERG:
|
|
IPCOM_LOG2(EMERG, "%s%s", prefix, hex_mem);
|
|
break;
|
|
case IPCOM_LOG_CRIT:
|
|
IPCOM_LOG2(CRIT, "%s%s", prefix, hex_mem);
|
|
break;
|
|
case IPCOM_LOG_ERR:
|
|
IPCOM_LOG2(ERR, "%s%s", prefix, hex_mem);
|
|
break;
|
|
case IPCOM_LOG_WARNING:
|
|
IPCOM_LOG2(WARNING, "%s%s", prefix, hex_mem);
|
|
break;
|
|
case IPCOM_LOG_NOTICE:
|
|
IPCOM_LOG2(NOTICE, "%s%s", prefix, hex_mem);
|
|
break;
|
|
case IPCOM_LOG_INFO:
|
|
IPCOM_LOG2(INFO, "%s%s", prefix, hex_mem);
|
|
break;
|
|
case IPCOM_LOG_DEBUG:
|
|
IPCOM_LOG2(DEBUG, "%s%s", prefix, hex_mem);
|
|
break;
|
|
case IPCOM_LOG_DEBUG2:
|
|
IPCOM_LOG2(DEBUG2, "%s%s", prefix, hex_mem);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
ipcom_free(hex_mem);
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_array_add
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_array_add(void ***array, void *elem)
|
|
{
|
|
void **new_array;
|
|
Ip_u32 length;
|
|
|
|
if (elem == IP_NULL)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_array_add: elem is NULL");
|
|
return IPIKE_TRIED_TO_ADD_NULL;
|
|
}
|
|
|
|
if (IP_NULL == *array && IP_NULL == (*array = ipcom_calloc(1, sizeof(void*))))
|
|
goto out_of_memory;
|
|
|
|
length = ipike_array_size(*array);
|
|
if (IP_NULL == (new_array = ipcom_realloc(*array, (2 + length) * sizeof(void*))))
|
|
goto out_of_memory;
|
|
|
|
new_array[length] = elem;
|
|
new_array[length + 1] = IP_NULL;
|
|
|
|
*array = new_array;
|
|
return IPIKE_SUCCESS;
|
|
|
|
out_of_memory:
|
|
IP_PANIC();
|
|
return IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_array_remove
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_array_remove(void ***array, void *elem, void(*free_func)(void*))
|
|
{
|
|
Ip_u32 i = 0;
|
|
|
|
#ifdef IPCOM_USE_DMALLOC
|
|
if (free_func == ipcom_free) /*lint !e123 */
|
|
free_func = ipcom_dfree;
|
|
#endif
|
|
|
|
while ((*array)[i] != IP_NULL)
|
|
{
|
|
if (elem == (*array)[i])
|
|
{
|
|
while ((*array)[i+1] != IP_NULL)
|
|
{
|
|
(*array)[i] = (*array)[i+1];
|
|
i++;
|
|
}
|
|
(*array)[i] = IP_NULL;
|
|
if (free_func)
|
|
free_func(elem);
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_array_size
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_u32
|
|
ipike_array_size(void **array)
|
|
{
|
|
Ip_u32 length = 0;
|
|
|
|
if (IP_NULL != array)
|
|
while (array[length] != IP_NULL)
|
|
length++;
|
|
|
|
return length;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_array_free
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_array_free(void **array, void(*free_func)(void*))
|
|
{
|
|
int i = 0;
|
|
|
|
#ifdef IPCOM_USE_DMALLOC
|
|
if (free_func == ipcom_free) /*lint !e123 */
|
|
free_func = ipcom_dfree;
|
|
#endif
|
|
|
|
if (IP_NULL == array)
|
|
return;
|
|
while (array[i] != IP_NULL)
|
|
{
|
|
void* ptr = array[i];
|
|
/* Fill the array with illegal addresses to catch
|
|
usage of the array after it has been freed.
|
|
Can not use IP_NULL since that is the end of array
|
|
marker */
|
|
array[i++] = (void*) -1;
|
|
if (free_func)
|
|
free_func(ptr);
|
|
}
|
|
ipcom_free(array);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_array_free_elements
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_array_free_elements(void ***array, void(*free_func)(void*))
|
|
{
|
|
Ip_u32 i = 0;
|
|
void *ptr;
|
|
|
|
#ifdef IPCOM_USE_DMALLOC
|
|
if (free_func == ipcom_free) /*lint !e123 */
|
|
free_func = ipcom_dfree;
|
|
#endif
|
|
|
|
if (IP_NULL == array)
|
|
return;
|
|
while (*array && (*array)[i] != IP_NULL)
|
|
{
|
|
ptr = (*array)[i];
|
|
(*array)[i++] = IP_NULL;
|
|
if (free_func)
|
|
free_func(ptr);
|
|
}
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_array_add_u8
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_array_add_u8(Ip_u8 n, Ip_u8*** array)
|
|
{
|
|
Ip_u8* p;
|
|
|
|
p = ipcom_malloc(sizeof(n));
|
|
if (IP_NULL == p)
|
|
{
|
|
IP_PANIC();
|
|
return IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
*p = n;
|
|
if (IPIKE_SUCCESS != ipike_array_add((void***)array, p))
|
|
{
|
|
IP_PANIC();
|
|
ipcom_free(p);
|
|
return IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_array_add_u32
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_array_add_u32(Ip_u32 n, Ip_u32*** array)
|
|
{
|
|
Ip_u32* p;
|
|
|
|
p = ipcom_malloc(sizeof(n));
|
|
if (IP_NULL == p)
|
|
{
|
|
IP_PANIC();
|
|
return IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
*p = n;
|
|
if (IPIKE_SUCCESS != ipike_array_add((void***)array, p))
|
|
{
|
|
IP_PANIC();
|
|
ipcom_free(p);
|
|
return IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_array_add_u64
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_array_add_u64(Ip_u64 n, Ip_u64*** array)
|
|
{
|
|
Ip_u64* p;
|
|
|
|
p = ipcom_malloc(sizeof(n));
|
|
if (IP_NULL == p)
|
|
{
|
|
IP_PANIC();
|
|
return IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
*p = n;
|
|
if (IPIKE_SUCCESS != ipike_array_add((void***)array, p))
|
|
{
|
|
IP_PANIC();
|
|
ipcom_free(p);
|
|
return IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_array_copy_u32
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_array_copy_u32(Ip_u32*** array_dst, Ip_u32** array_src)
|
|
{
|
|
Ipike_error err;
|
|
int i;
|
|
|
|
if (IP_NULL != array_src)
|
|
{
|
|
for (i=0; array_src[i] != IP_NULL; i++)
|
|
{
|
|
if (IPIKE_SUCCESS != (err = ipike_array_add_u32(
|
|
*array_src[i],
|
|
array_dst)))
|
|
{
|
|
return err;
|
|
}
|
|
}
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_array_copy_u64
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_array_copy_u64(Ip_u64*** array_dst, Ip_u64** array_src)
|
|
{
|
|
Ipike_error err;
|
|
int i;
|
|
|
|
if (IP_NULL != array_src)
|
|
{
|
|
for (i=0; array_src[i] != IP_NULL; i++)
|
|
{
|
|
if (IPIKE_SUCCESS != (err = ipike_array_add_u64(
|
|
*array_src[i],
|
|
array_dst)))
|
|
{
|
|
return err;
|
|
}
|
|
}
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_map_int
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_map_int(const Ipike_string_int_map map[], const char *key, int *value)
|
|
{
|
|
Ipike_error err;
|
|
const Ipike_string_int_map *map_iter;
|
|
char *tmp;
|
|
|
|
if ((key == IP_NULL) || (map == IP_NULL))
|
|
return IPIKE_INVALID_VALUE;
|
|
/* key may be a list of entries separated with ',' */
|
|
if (IPIKE_SUCCESS != (err = ipike_parse_get_first_string(key, ',', &tmp)))
|
|
return err;
|
|
for (map_iter = map; map_iter->key != IP_NULL; map_iter++)
|
|
{
|
|
if (0 == ipcom_strcasecmp(tmp, map_iter->key))
|
|
{
|
|
ipcom_free(tmp);
|
|
*value = map_iter->value;
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
}
|
|
ipcom_free(tmp);
|
|
return IPIKE_VALUE_NOT_FOUND;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_map_string
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_map_string(const Ipike_string_int_map map[], int key, const char **value)
|
|
{
|
|
const Ipike_string_int_map* map_iter;
|
|
|
|
if (map == IP_NULL)
|
|
return IPIKE_INVALID_VALUE;
|
|
for (map_iter = map; map_iter->key != IP_NULL; map_iter++)
|
|
{
|
|
if (map_iter->value == key)
|
|
{
|
|
*value = map_iter->key;
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
}
|
|
return IPIKE_VALUE_NOT_FOUND;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_strvec
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL char **
|
|
ipike_strvec(const char* s, const char* delimiter)
|
|
{
|
|
char **ret = IP_NULL;
|
|
char *token;
|
|
char *str;
|
|
char *last;
|
|
Ip_bool success = IP_FALSE;
|
|
|
|
if (s == IP_NULL)
|
|
return IP_NULL;
|
|
str = ipcom_strdup(s);
|
|
if (str == IP_NULL)
|
|
return IP_FALSE;
|
|
|
|
for (token = ipcom_strtok_r(str, delimiter, &last);
|
|
token != IP_NULL;
|
|
token = ipcom_strtok_r(IP_NULL, delimiter, &last))
|
|
{
|
|
char* arr_add = ipcom_strdup(token);
|
|
if (IP_NULL == arr_add)
|
|
goto cleanup;
|
|
if (ipike_array_add((void***) &ret, arr_add))
|
|
goto cleanup;
|
|
}
|
|
success = IP_TRUE;
|
|
|
|
cleanup:
|
|
if (!success)
|
|
{
|
|
ipike_array_free((void**) ret, ipcom_free); /*lint !e123 */
|
|
ret = IP_NULL;
|
|
}
|
|
ipcom_free(str);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_addr_to_str
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL const char *
|
|
ipike_addr_to_str(const union Ip_sockaddr_union* addr)
|
|
{
|
|
return ipike_addr_to_str_buf(addr, ipike.addr_buf, sizeof(ipike.addr_buf));
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_addr_to_str_buf
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL const char *
|
|
ipike_addr_to_str_buf(
|
|
const union Ip_sockaddr_union* addr,
|
|
char* buf,
|
|
Ip_size_t size)
|
|
{
|
|
switch (addr->sa.sa_family)
|
|
{
|
|
#ifdef IPCOM_USE_INET
|
|
case IP_AF_INET:
|
|
return ipcom_inet_ntop(IP_AF_INET, &addr->sin.sin_addr, buf, size);
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
case IP_AF_INET6:
|
|
return ipcom_inet_ntop(IP_AF_INET6, &addr->sin6.sin6_addr, buf, size);
|
|
#endif
|
|
default:
|
|
return IP_NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_addr_subnet_to_str
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL const char *
|
|
ipike_addr_subnet_to_str(
|
|
const union Ip_sockaddr_union* addr,
|
|
const union Ip_sockaddr_union* mask)
|
|
{
|
|
return ipike_addr_subnet_to_str_buf(addr, mask, ipike.addr_buf, sizeof(ipike.addr_buf));
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_addr_subnet_to_str_buf
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL const char *
|
|
ipike_addr_subnet_to_str_buf(
|
|
const union Ip_sockaddr_union* addr,
|
|
const union Ip_sockaddr_union* mask,
|
|
char* buf,
|
|
Ip_size_t size)
|
|
{
|
|
int prefix_len;
|
|
const char* psz;
|
|
|
|
switch (addr->sa.sa_family)
|
|
{
|
|
#ifdef IPCOM_USE_INET
|
|
case IP_AF_INET:
|
|
psz = ipcom_inet_ntop(IP_AF_INET, &addr->sin.sin_addr, buf, size);
|
|
break;
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
case IP_AF_INET6:
|
|
psz = ipcom_inet_ntop(IP_AF_INET6, &addr->sin6.sin6_addr, buf, size);
|
|
break;
|
|
#endif
|
|
default:
|
|
return IP_NULL;
|
|
}
|
|
prefix_len = ipcom_sockaddr_to_prefixlen((struct Ip_sockaddr*)mask);
|
|
if (psz==IP_NULL)
|
|
return IP_NULL;
|
|
ipcom_sprintf((char*)&psz[ipcom_strlen(psz)], "/%d", prefix_len);
|
|
|
|
return psz;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_addr_range_to_str_buf
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL const char *
|
|
ipike_addr_range_to_str_buf(
|
|
const union Ip_sockaddr_union* low,
|
|
const union Ip_sockaddr_union* high,
|
|
char* buf,
|
|
Ip_size_t size)
|
|
{
|
|
Ip_size_t low_len;
|
|
|
|
if ( !ipike_addr_to_str_buf(low, buf, size) )
|
|
return IP_NULL;
|
|
|
|
low_len = ipcom_strlen(buf);
|
|
|
|
if ( size <= low_len + 1)
|
|
return IP_NULL;
|
|
|
|
/* Replace '\0' with '-' */
|
|
buf[low_len] = '-';
|
|
|
|
if ( !ipike_addr_to_str_buf(high, buf + low_len + 1, size - low_len - 1) )
|
|
return IP_NULL;
|
|
|
|
return buf;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_addr_compare
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL int
|
|
ipike_addr_compare(
|
|
const union Ip_sockaddr_union* addr1,
|
|
const union Ip_sockaddr_union* addr2)
|
|
{
|
|
if (!addr1 || !addr2 ||
|
|
addr1->sa.sa_family != addr2->sa.sa_family)
|
|
{
|
|
return 0;
|
|
}
|
|
switch (addr1->sa.sa_family)
|
|
{
|
|
#ifdef IPCOM_USE_INET
|
|
case IP_AF_INET:
|
|
if (ip_ntohl(addr1->sin.sin_addr.s_addr) > ip_ntohl(addr2->sin.sin_addr.s_addr))
|
|
return 1;
|
|
else if (ip_ntohl(addr1->sin.sin_addr.s_addr) < ip_ntohl(addr2->sin.sin_addr.s_addr))
|
|
return -1;
|
|
break;
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
case IP_AF_INET6:
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
if (ip_ntohl(addr1->sin6.sin6_addr.in6.addr32[i]) > ip_ntohl(addr2->sin6.sin6_addr.in6.addr32[i]))
|
|
return 1;
|
|
if (ip_ntohl(addr1->sin6.sin6_addr.in6.addr32[i]) < ip_ntohl(addr2->sin6.sin6_addr.in6.addr32[i]))
|
|
return -1;
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
/* Same */
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_addr_match_socket
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipike_addr_match_socket(union Ip_sockaddr_union* bind_addr, int sock)
|
|
{
|
|
union Ip_sockaddr_union name;
|
|
Ip_socklen_t namelen = sizeof(name);
|
|
int ret;
|
|
|
|
ret = ipcom_getsockname(sock, &name.sa, &namelen);
|
|
|
|
if (ret < 0)
|
|
{
|
|
IPCOM_LOG1(ERR,
|
|
"ipike_addr_match_socket() :: "\
|
|
"ipcom_getsockname failed returned: errno=%d",
|
|
ipcom_errno);
|
|
return IP_FALSE;
|
|
}
|
|
|
|
/* This check is only needed if :: or 0.0.0.0 is allowed */
|
|
#if defined(IPIKE_USE_PKTINFO)
|
|
if (
|
|
#ifdef IPCOM_USE_INET
|
|
(
|
|
name.sa.sa_family == IP_AF_INET &&
|
|
name.sin.sin_addr.s_addr == IP_INADDR_ANY &&
|
|
name.sa.sa_family == bind_addr->sa.sa_family &&
|
|
name.sin.sin_port == bind_addr->sin.sin_port)
|
|
#else
|
|
0
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
|| (name.sa.sa_family == IP_AF_INET6 &&
|
|
IP_IN6_ARE_ADDR_EQUAL(&(name.sin6.sin6_addr),&ip_in6addr_any) &&
|
|
name.sa.sa_family == bind_addr->sa.sa_family &&
|
|
name.sin6.sin6_port == bind_addr->sin6.sin6_port)
|
|
#else
|
|
|| 0
|
|
#endif
|
|
)
|
|
return IP_TRUE;
|
|
#endif
|
|
|
|
return ipike_addr_are_equal_port(&name, bind_addr);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_are_addr_equal
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipike_addr_are_equal(
|
|
const union Ip_sockaddr_union* a1,
|
|
const union Ip_sockaddr_union* a2)
|
|
{
|
|
switch (a1->sa.sa_family)
|
|
{
|
|
#ifdef IPCOM_USE_INET
|
|
case IP_AF_INET:
|
|
{
|
|
struct Ip_sockaddr_in* in1 = (struct Ip_sockaddr_in*) &a1->sin;
|
|
struct Ip_sockaddr_in* in2 = (struct Ip_sockaddr_in*) &a2->sin;
|
|
|
|
return a2->sa.sa_family == IP_AF_INET
|
|
&& in1->sin_addr.s_addr == in2->sin_addr.s_addr;
|
|
}
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
case IP_AF_INET6:
|
|
{
|
|
struct Ip_sockaddr_in6* in1 = (struct Ip_sockaddr_in6*) &a1->sin6;
|
|
struct Ip_sockaddr_in6* in2 = (struct Ip_sockaddr_in6*) &a2->sin6;
|
|
|
|
return a2->sa.sa_family == IP_AF_INET6
|
|
&& IP_IN6_ARE_ADDR_EQUAL(&in1->sin6_addr, &in2->sin6_addr);
|
|
}
|
|
#endif
|
|
default:
|
|
IP_PANIC();
|
|
return IP_FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_addr_are_equal_port
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipike_addr_are_equal_port(
|
|
const union Ip_sockaddr_union* a1,
|
|
const union Ip_sockaddr_union* a2)
|
|
{
|
|
if (!ipike_addr_are_equal(a1, a2))
|
|
return IP_FALSE;
|
|
|
|
switch (a1->sa.sa_family)
|
|
{
|
|
#ifdef IPCOM_USE_INET
|
|
case IP_AF_INET:
|
|
return (a1->sin.sin_port == a2->sin.sin_port);
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
case IP_AF_INET6:
|
|
return (a1->sin6.sin6_port == a2->sin6.sin6_port);
|
|
#endif
|
|
}
|
|
|
|
IP_PANIC();
|
|
return IP_FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_get_addr_ptr
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void *
|
|
ipike_addr_get_ptr(union Ip_sockaddr_union *addr)
|
|
{
|
|
switch (addr->sa.sa_family)
|
|
{
|
|
#ifdef IPCOM_USE_INET
|
|
case IP_AF_INET:
|
|
return &addr->sin.sin_addr;
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
case IP_AF_INET6:
|
|
return &addr->sin6.sin6_addr;
|
|
#endif
|
|
default:
|
|
IP_PANIC();
|
|
return IP_FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_get_addr_len
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_u8
|
|
ipike_addr_get_len(const union Ip_sockaddr_union *addr)
|
|
{
|
|
switch (addr->sa.sa_family)
|
|
{
|
|
#ifdef IPCOM_USE_INET
|
|
case IP_AF_INET:
|
|
return 4;
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
case IP_AF_INET6:
|
|
return 16;
|
|
#endif
|
|
default:
|
|
IP_PANIC();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_is_zero_addr
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipike_addr_is_zero(union Ip_sockaddr_union *addr)
|
|
{
|
|
Ip_u8* p;
|
|
Ip_u32 n;
|
|
|
|
p = ipike_addr_get_ptr(addr);
|
|
n = ipike_addr_get_len(addr);
|
|
while (n > 0)
|
|
if (p[--n] != 0)
|
|
return IP_FALSE;
|
|
|
|
return IP_TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_set_address
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_addr_set(
|
|
union Ip_sockaddr_union* addr,
|
|
const char* ip)
|
|
{
|
|
if (IP_NULL == ip)
|
|
return IPIKE_FAILED;
|
|
|
|
ipcom_memset(addr, 0, sizeof(*addr));
|
|
/* Assume interface name and try to get primary address */
|
|
if (!ipike_get_if_addr(ip, addr))
|
|
{
|
|
/* Assume IPv4 address and try IPv6 if fails */
|
|
#ifdef IPCOM_USE_INET
|
|
if (addr->sa.sa_family == 0)
|
|
{
|
|
if (ipike_inet_pton(IP_AF_INET, ip, &addr->sin.sin_addr) != 0)
|
|
{
|
|
addr->sa.sa_family = IP_AF_INET;
|
|
IPCOM_SA_LEN_SET(&addr->sa, sizeof (struct Ip_sockaddr_in));
|
|
}
|
|
else
|
|
{
|
|
addr->sa.sa_family = 0;
|
|
}
|
|
}
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
if (addr->sa.sa_family == 0)
|
|
{
|
|
if (ipike_inet_pton(IP_AF_INET6, ip, &addr->sin6.sin6_addr) != 0)
|
|
{
|
|
/* getsockaddrbyaddr for obtaining scope of v6 llocal addrs */
|
|
ipcom_getsockaddrbyaddr(IP_AF_INET6,ip,&addr->sa);
|
|
}
|
|
else
|
|
{
|
|
addr->sa.sa_family = 0;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
if (addr->sa.sa_family == 0)
|
|
{
|
|
IPCOM_LOG1(DEBUG, "ipike_addr_set() :: bad address: %s", ip);
|
|
return IPIKE_FAILED;
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_set_address_from_data
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_addr_set_from_data(
|
|
Ip_u8* data,
|
|
Ip_size_t len,
|
|
union Ip_sockaddr_union* addr)
|
|
{
|
|
ipcom_memset(addr, 0, sizeof(*addr));
|
|
#ifdef IPCOM_USE_INET
|
|
if (len == 4)
|
|
{
|
|
addr->sa.sa_family = IP_AF_INET;
|
|
IPCOM_SA_LEN_SET(&addr->sa, sizeof (struct Ip_sockaddr_in));
|
|
ipcom_memcpy((void*)&addr->sin.sin_addr, data, len);
|
|
}
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
if (len == 16)
|
|
{
|
|
addr->sa.sa_family = IP_AF_INET6;
|
|
IPCOM_SA_LEN_SET(&addr->sa, sizeof (struct Ip_sockaddr_in6));
|
|
ipcom_memcpy((void*)&addr->sin6.sin6_addr, data, len);
|
|
}
|
|
#endif
|
|
if (addr->sa.sa_family == 0)
|
|
return IPIKE_FAILED;
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_append_address_from_data
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_addr_append_from_data(Ip_u8* data, Ip_size_t len, union Ip_sockaddr_union*** list)
|
|
{
|
|
Ipike_error err = IPIKE_SUCCESS;
|
|
union Ip_sockaddr_union* addr = IP_NULL;
|
|
|
|
addr = ipcom_calloc(1, sizeof(*addr));
|
|
if (IP_NULL == addr)
|
|
{
|
|
IP_PANIC();
|
|
err = IPIKE_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
err = ipike_addr_set_from_data(data, len, addr);
|
|
if (IPIKE_SUCCESS == err)
|
|
err = ipike_array_add((void***)list, addr);
|
|
if (IPIKE_SUCCESS != err)
|
|
ipcom_free(addr);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_set_port
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_addr_set_port(union Ip_sockaddr_union* addr, Ip_u16 port)
|
|
{
|
|
switch (addr->sa.sa_family)
|
|
{
|
|
#ifdef IPCOM_USE_INET
|
|
case IP_AF_INET:
|
|
addr->sin.sin_port = ip_htons(port);
|
|
break;
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
case IP_AF_INET6:
|
|
addr->sin6.sin6_port = ip_htons(port);
|
|
break;
|
|
#endif
|
|
default:
|
|
#if defined(IPCOM_USE_INET6)
|
|
addr->sin6.sin6_port = ip_htons(port);
|
|
#elif defined(IPCOM_USE_INET)
|
|
addr->sin.sin_port = ip_htons(port);
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_addr_get_port
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_u16
|
|
ipike_addr_get_port(const union Ip_sockaddr_union* addr)
|
|
{
|
|
Ip_u16 port = 0;
|
|
|
|
switch (addr->sa.sa_family)
|
|
{
|
|
#ifdef IPCOM_USE_INET
|
|
case IP_AF_INET:
|
|
port = ip_ntohs(addr->sin.sin_port);
|
|
break;
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
case IP_AF_INET6:
|
|
port = ip_ntohs(addr->sin6.sin6_port);
|
|
break;
|
|
#endif
|
|
default:
|
|
/* Try get any port information */
|
|
#ifdef IPCOM_USE_INET6
|
|
port = ip_ntohs(addr->sin6.sin6_port);
|
|
#endif
|
|
#ifdef IPCOM_USE_INET
|
|
port = ip_ntohs(addr->sin.sin_port);
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
return port;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_copy_address
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_addr_copy(
|
|
union Ip_sockaddr_union *to,
|
|
const union Ip_sockaddr_union *from)
|
|
{
|
|
Ipike_error err = IPIKE_SUCCESS;
|
|
|
|
ipcom_memset(to, 0, sizeof(*to));
|
|
|
|
switch (from->sa.sa_family)
|
|
{
|
|
#ifdef IPCOM_USE_INET
|
|
case IP_AF_INET:
|
|
ipcom_memcpy((void*)to, (void*)from, sizeof (struct Ip_sockaddr_in));
|
|
IPCOM_SA_LEN_SET(&to->sa, sizeof (struct Ip_sockaddr_in));
|
|
break;
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
case IP_AF_INET6:
|
|
ipcom_memcpy((void*)to, (void*)from, sizeof (struct Ip_sockaddr_in6));
|
|
IPCOM_SA_LEN_SET(&to->sa, sizeof (struct Ip_sockaddr_in6));
|
|
break;
|
|
#endif
|
|
default:
|
|
/* Should never happen */
|
|
IP_PANIC();
|
|
err = IPIKE_FAILED;
|
|
break;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_has_valid_address
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipike_addr_is_valid(const union Ip_sockaddr_union* addr)
|
|
{
|
|
#ifdef IPCOM_USE_INET
|
|
if (addr->sa.sa_family == IP_AF_INET)
|
|
return IP_TRUE;
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
if (addr->sa.sa_family == IP_AF_INET6)
|
|
return IP_TRUE;
|
|
#endif
|
|
|
|
return IP_FALSE;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_addr_match_network
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipike_addr_match_network(
|
|
union Ip_sockaddr_union* address,
|
|
union Ip_sockaddr_union* network,
|
|
union Ip_sockaddr_union* netmask)
|
|
{
|
|
union Ip_sockaddr_union address2;
|
|
union Ip_sockaddr_union address3;
|
|
|
|
if ((ipike_addr_copy(&address2, address) == IPIKE_SUCCESS) &&
|
|
(ipike_addr_copy(&address3, network) == IPIKE_SUCCESS) &&
|
|
(ipike_addr_apply_network_mask(&address2, netmask) == IPIKE_SUCCESS) &&
|
|
(ipike_addr_apply_network_mask(&address3, netmask) == IPIKE_SUCCESS) &&
|
|
(ipike_addr_compare(&address2, &address3) == 0))
|
|
{
|
|
return IP_TRUE;
|
|
}
|
|
|
|
return IP_FALSE;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_addr_match_range
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipike_addr_match_range(
|
|
const union Ip_sockaddr_union* addr,
|
|
const union Ip_sockaddr_union* low,
|
|
const union Ip_sockaddr_union* high)
|
|
{
|
|
if ( ipike_addr_compare(addr, low) < 0 )
|
|
return IP_FALSE;
|
|
|
|
if ( ipike_addr_compare(addr, high) > 0 )
|
|
return IP_FALSE;
|
|
|
|
return IP_TRUE;
|
|
}
|
|
/*
|
|
*===========================================================================
|
|
* ipike_addr_range_to_mask
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_addr_range_to_mask(
|
|
union Ip_sockaddr_union* addr,
|
|
union Ip_sockaddr_union* mask)
|
|
{
|
|
Ip_u8* p1;
|
|
Ip_u8* p2;
|
|
Ip_u32 len;
|
|
Ip_u32 i;
|
|
|
|
p1 = ipike_addr_get_ptr(addr);
|
|
len = ipike_addr_get_len(addr);
|
|
p2 = ipike_addr_get_ptr(mask);
|
|
if (len != ipike_addr_get_len(mask))
|
|
return IPIKE_FAILED;
|
|
|
|
for (i=0; i<len; i++)
|
|
{
|
|
if (p1[i] != p2[i])
|
|
{
|
|
p1[i] &= p2[i];
|
|
p2[i] = (Ip_u8)(~((Ip_u8)(p2[i] - p1[i])));
|
|
i++;
|
|
break;
|
|
}
|
|
p2[i] = 0xff;
|
|
}
|
|
for (; i<len; i++)
|
|
{
|
|
p1[i] = 0;
|
|
p2[i] = 0;
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_addr_mask_to_range
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_addr_mask_to_range(
|
|
union Ip_sockaddr_union* addr,
|
|
union Ip_sockaddr_union* mask)
|
|
{
|
|
Ip_u8* p1;
|
|
Ip_u8* p2;
|
|
Ip_u32 len;
|
|
Ip_u32 i;
|
|
Ip_u32 j;
|
|
Ip_u8 b;
|
|
|
|
p1 = ipike_addr_get_ptr(addr);
|
|
len = ipike_addr_get_len(addr);
|
|
p2 = ipike_addr_get_ptr(mask);
|
|
if (len != ipike_addr_get_len(mask))
|
|
return IPIKE_FAILED;
|
|
|
|
for (i=0; i<len; i++)
|
|
{
|
|
if (p2[i] != 0xff)
|
|
{
|
|
b = p2[i];
|
|
p1[i] &= p2[i];
|
|
p2[i] = p1[i];
|
|
for (j=0; j<8; j++)
|
|
if (((1 << j) & b) == 0)
|
|
p2[i] |= (Ip_u8)(1 << j);
|
|
else
|
|
break;
|
|
i++;
|
|
break;
|
|
}
|
|
p2[i] = p1[i];
|
|
}
|
|
for (; i<len; i++)
|
|
{
|
|
p1[i] = 0;
|
|
p2[i] = 0xff;
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_addr_apply_network_mask
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_addr_apply_network_mask(
|
|
union Ip_sockaddr_union* addr,
|
|
union Ip_sockaddr_union* mask)
|
|
{
|
|
Ip_u8* p1;
|
|
Ip_u8* p2;
|
|
Ip_u32 len;
|
|
Ip_u32 i;
|
|
|
|
p1 = ipike_addr_get_ptr(addr);
|
|
len = ipike_addr_get_len(addr);
|
|
p2 = ipike_addr_get_ptr(mask);
|
|
if (len != ipike_addr_get_len(mask))
|
|
return IPIKE_FAILED;
|
|
|
|
for (i=0; i<len; i++)
|
|
p1[i] &= p2[i];
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_addr_load_subnet
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_addr_load_subnet(
|
|
const char* network,
|
|
union Ip_sockaddr_union* addr,
|
|
union Ip_sockaddr_union* mask)
|
|
{
|
|
Ipike_error err;
|
|
Ip_u8* pb;
|
|
Ip_u32 n;
|
|
int n2;
|
|
|
|
if (IPIKE_SUCCESS != (err = ipike_addr_set(addr, network)))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_load_subnet: bad network");
|
|
return err;
|
|
}
|
|
if (IPIKE_SUCCESS != (err = ipike_addr_set(mask, network)))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_load_subnet: bad netmask");
|
|
return err;
|
|
}
|
|
pb = ipike_addr_get_ptr(mask);
|
|
n = ipike_addr_get_len(mask);
|
|
|
|
if (IP_NULL != (network = ipcom_strchr(network, '/')))
|
|
{
|
|
ipcom_memset(pb, 0x00, n);
|
|
n2 = ipcom_atoi(network+1);
|
|
if ((n2 / 8) > (int) n )
|
|
{
|
|
IPCOM_LOG1(ERR, "ipike_load_subnet: bad netmask (%d)", n2);
|
|
return IPIKE_CONF_INVALID_VALUE;
|
|
}
|
|
ipike_addr_create_mask(pb,n2, IP_FALSE);
|
|
}
|
|
else
|
|
{
|
|
/* default 0xff */
|
|
ipcom_memset(pb, 0xff, n);
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_addr_create_mask
|
|
*===========================================================================
|
|
* Description: Creates a network mask with the 'netbits' leftmost bits set.
|
|
* Parameters: [in] mask - Pointer to a buffer where the mask should be stored.
|
|
* [in] netbits - The number of set bits.
|
|
* [in] inverse - inverse of netmask if true
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_addr_create_mask(void *mask, int netbits, Ip_bool inverse)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < netbits; i++)
|
|
{
|
|
if (inverse == IP_TRUE)
|
|
IP_BIT_CLR(((Ip_u16*) mask)[i / 16], ip_htons(0x8000 >> (i % 16)));
|
|
else
|
|
IP_BIT_SET(((Ip_u16*) mask)[i / 16], ip_htons(0x8000 >> (i % 16)));
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_increment_v6_address
|
|
*===========================================================================
|
|
* Description: Given an v6 address and mask increments it
|
|
* Parameters: [in] address - v6 address
|
|
* [in] prefixlen - v6 prefix
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_addr_increment_v6(union Ip_sockaddr_union *address, int prefixlen)
|
|
{
|
|
#ifdef IPCOM_USE_INET6
|
|
int i;
|
|
Ip_u32 addrcur, tmp;
|
|
Ip_u8 *ptmpaddr, *pmaxaddr;
|
|
struct Ip_in6_addr *addr;
|
|
union Ip_sockaddr_union tmpaddr, maxaddr, tmpaddr1;
|
|
Ip_bool overflow = IP_TRUE;
|
|
|
|
/* Make a copy of the address */
|
|
ipcom_memcpy(&maxaddr,address,sizeof(union Ip_sockaddr_union));
|
|
|
|
/* Backup copy used to revert */
|
|
ipcom_memcpy(&tmpaddr1,address,sizeof(union Ip_sockaddr_union));
|
|
tmpaddr.sa.sa_family = IP_AF_INET6;
|
|
|
|
ptmpaddr = (Ip_u8*)ipike_addr_get_ptr(&tmpaddr);
|
|
pmaxaddr = (Ip_u8*)ipike_addr_get_ptr(&maxaddr);
|
|
|
|
if (prefixlen == 128 || prefixlen == 0)
|
|
{
|
|
/* Max addr is FFFF...FFFF */
|
|
ipcom_memset(pmaxaddr,0xFF,16);
|
|
}
|
|
else
|
|
{
|
|
i = ipike_addr_get_len(address);
|
|
|
|
ipcom_memset(ptmpaddr,0x00,(Ip_size_t) i);
|
|
tmpaddr.sa.sa_family = IP_AF_INET6;
|
|
|
|
ipike_addr_create_mask(ptmpaddr,prefixlen,IP_FALSE);
|
|
|
|
(void)ipike_addr_apply_network_mask(&maxaddr,&tmpaddr);
|
|
|
|
ipcom_memset(ptmpaddr,0xFF,(Ip_size_t) i);
|
|
tmpaddr.sa.sa_family = IP_AF_INET6;
|
|
|
|
ipike_addr_create_mask(ptmpaddr,prefixlen,IP_TRUE);
|
|
|
|
/* Add the maxaddr + inverse mask to get max addr */
|
|
i--; /* i = addr_len -1 => 15 */
|
|
for (; i >= 0; i--)
|
|
pmaxaddr[i] |= ptmpaddr[i];
|
|
}
|
|
|
|
addr = ipike_addr_get_ptr(address);
|
|
|
|
for (i = 3; i >= 0; i--)
|
|
{
|
|
addrcur = (IP_GET_32ON16(&((struct Ip_in6_addr *)(addr))->in6.addr32[i]));
|
|
/* Handle overflo */
|
|
if (addrcur == 0xffffffffU && overflow == IP_TRUE)
|
|
{
|
|
IP_SET_32ON16(&(addr)->in6.addr32[i], 0);
|
|
}
|
|
else
|
|
{
|
|
tmp = ip_ntohl(addrcur) + 1;
|
|
IP_SET_HTONL(&(addr)->in6.addr32[i], tmp);
|
|
overflow = IP_FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (IP_IN6_ARE_ADDR_EQUAL((struct Ip_in6_addr*)addr, (struct Ip_in6_addr*)pmaxaddr))
|
|
{
|
|
IPCOM_LOG3(ERR,
|
|
"ipike_increment_v6_address: Max limit addr:%s max:%s resetting to %s \n",
|
|
ipike_addr_to_str(address), ipike_addr_to_str(&maxaddr),
|
|
ipike_addr_to_str(&tmpaddr1) );
|
|
return IPIKE_FAILED;
|
|
}
|
|
#endif /* IPCOM_USE_INET6 */
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_load_ike_address
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_to_lower_string(char *str)
|
|
{
|
|
int i = 0;
|
|
|
|
if (IP_NULL != str)
|
|
{
|
|
while (str[i] != 0)
|
|
{
|
|
str[i] = (char)ipcom_tolower(str[i]);
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_hex2bin
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_u8*
|
|
ipike_hex2bin(const char* value, Ip_size_t* len)
|
|
{
|
|
Ip_u8* res;
|
|
Ip_size_t i;
|
|
char c;
|
|
|
|
*len = *len / 2;
|
|
res = ipcom_malloc(*len);
|
|
if (res != IP_NULL)
|
|
{
|
|
for (i=0; i<*len; i++)
|
|
{
|
|
c = value[2*i];
|
|
if ((c >= '0') && (c <= '9'))
|
|
res[i] = (Ip_u8)((c - '0') << 4);
|
|
else if ((c >= 'A') && (c <= 'F'))
|
|
res[i] = (Ip_u8)((c - 'A' + 10) << 4);
|
|
else if ((c >= 'a') && (c <= 'f'))
|
|
res[i] = (Ip_u8)((c - 'a' + 10) << 4);
|
|
else
|
|
res[i] = 0;
|
|
c = value[2*i+1];
|
|
if ((c >= '0') && (c <= '9'))
|
|
res[i] = (Ip_u8)(res[i] + c - '0');
|
|
else if ((c >= 'A') && (c <= 'F'))
|
|
res[i] = (Ip_u8)(res[i] + c - 'A' + 10);
|
|
else if ((c >= 'a') && (c <= 'f'))
|
|
res[i] = (Ip_u8)(res[i] + c - 'a' + 10);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_bin2hex
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_bin2hex(unsigned char* buf, Ip_size_t len, char* value)
|
|
{
|
|
Ip_size_t i;
|
|
char nibble;
|
|
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
/* First nibble */
|
|
nibble = (char)((buf[i] >> 4) & 0x0F);
|
|
|
|
if (nibble < 10)
|
|
value[i * 2] = (char)(nibble + '0');
|
|
else
|
|
value[i * 2] = (char)(nibble + 'a' - 10);
|
|
|
|
/* Second nibble */
|
|
nibble = (char)(buf[i] & 0x0F);
|
|
|
|
if (nibble < 10)
|
|
value[i * 2 + 1] = (char)(nibble + '0');
|
|
else
|
|
value[i * 2 + 1] = (char)(nibble + 'a' - 10);
|
|
}
|
|
|
|
value[2 * len] = '\0';
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_write_file
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_write_file(const char* filename, Ip_u8* buf, Ip_size_t buf_len)
|
|
{
|
|
Ipike_error err = 0;
|
|
IP_FILE* file = IP_NULL;
|
|
Ip_size_t total = 0;
|
|
Ip_size_t len = 0;
|
|
|
|
file = ipcom_fopen(filename, "w");
|
|
if (IP_NULL == file)
|
|
{
|
|
err = IPIKE_FAILED;
|
|
}
|
|
else
|
|
{
|
|
while ((IPIKE_SUCCESS == err) && (total < buf_len))
|
|
{
|
|
len = ipcom_fwrite(&buf[len], 1, buf_len, file);
|
|
if (len <= 0)
|
|
err = IPIKE_FAILED;
|
|
else
|
|
total += len;
|
|
}
|
|
(void)ipcom_fclose(file);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_read_file
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_read_file(const char* filename, Ip_u8** buf, Ip_size_t* buf_len)
|
|
{
|
|
Ipike_error err = 0;
|
|
IP_FILE* file = IP_NULL;
|
|
Ip_size_t total = 0;
|
|
Ip_size_t len = 0;
|
|
|
|
file = ipcom_fopen(filename, "r");
|
|
if (IP_NULL == file)
|
|
{
|
|
err = IPIKE_FAILED;
|
|
}
|
|
else
|
|
{
|
|
*buf_len = 0;
|
|
while (total == *buf_len)
|
|
{
|
|
len = (1024 + *buf_len)*2;
|
|
total += len;
|
|
*buf = ipcom_realloc(*buf, total);
|
|
len = ipcom_fread(&(*buf)[*buf_len], 1, len, file);
|
|
*buf_len += len;
|
|
}
|
|
(void)ipcom_fclose(file);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_tmo2_cancel
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL void
|
|
ipike_tmo2_cancel(Ipcom_tmo2 *tmo)
|
|
{
|
|
if (IPCOM_TMO2_PENDING(tmo) == IP_TRUE)
|
|
{
|
|
(void)ipcom_tmo2_cancel(tmo);
|
|
ipcom_memset(tmo, 0, sizeof(*tmo));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_get_if_addr
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipike_get_if_addr(const char* name, union Ip_sockaddr_union* addr)
|
|
{
|
|
Ip_bool found_address = IP_FALSE;
|
|
struct Ip_if_nameindex *ni;
|
|
int i;
|
|
#ifdef IPCOM_USE_INET
|
|
struct Ip_ifreq ifreq;
|
|
#else
|
|
struct Ip_in6_ifreq ifxreq;
|
|
#endif
|
|
Ip_fd s;
|
|
int retry_count;
|
|
|
|
if ((ni = ipcom_if_nameindex()) == IP_NULL)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_get_if_addr: failed to get interface list");
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; ni[i].if_name != IP_NULL && !found_address; i++)
|
|
{
|
|
if ((ipcom_strcmp(ni[i].if_name, "lo0") == 0) ||
|
|
(ipcom_strcmp(ni[i].if_name, "lo") == 0))
|
|
continue;
|
|
if ((name != IP_NULL) && (ipcom_strcmp(ni[i].if_name, name) != 0))
|
|
continue;
|
|
#ifdef IPCOM_USE_INET
|
|
ipcom_strncpy(ifreq.ifr_name, ni[i].if_name,IP_IFNAMSIZ - 1);
|
|
#else
|
|
ipcom_strncpy(ifxreq.ifr_name, ni[i].if_name,IP_IFNAMSIZ - 1);
|
|
ifxreq.ifr_ifru.ifru_addr.sin6_family = IP_AF_INET6;
|
|
IPCOM_SA_LEN_SET(&ifxreq.ifr_ifru.ifru_addr, sizeof(struct Ip_sockaddr_in6));
|
|
#endif
|
|
#ifdef IPCOM_USE_INET
|
|
if ((s = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, 0)) == IP_INVALID_SOCKET)
|
|
#else
|
|
if ((s = ipcom_socket(IP_AF_INET6, IP_SOCK_DGRAM, 0)) == IP_INVALID_SOCKET)
|
|
#endif
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_get_if_addr: failed to create socket");
|
|
}
|
|
else
|
|
{
|
|
/* We have found the interface, let's get the primary address.
|
|
* Loop for X seconds, since DHCP client may be trying to get
|
|
* the address */
|
|
retry_count = ipcom_sysvar_get_as_int("ipike.get_address_retry", 30);
|
|
if (retry_count == 0)
|
|
retry_count = 1;
|
|
while (retry_count > 0)
|
|
{
|
|
#ifdef IPCOM_USE_INET
|
|
if ((ipcom_socketioctl(s, IP_SIOCGIFADDR, &ifreq) < 0) ||
|
|
ipike_addr_is_zero((union Ip_sockaddr_union*)&ifreq.ip_ifr_addr))
|
|
#else
|
|
if ((ipcom_socketioctl(s, IP_SIOCGIFADDR_IN6, &ifxreq) < 0) ||
|
|
ipike_addr_is_zero((union Ip_sockaddr_union*)&ifxreq.ifr_ifru.ifru_addr))
|
|
#endif
|
|
{
|
|
IPCOM_LOG1(DEBUG2, "ipike_get_if_addr: failed to get primary address from %s", ni[i].if_name);
|
|
(void)ipcom_sleep(1);
|
|
retry_count--;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if ((retry_count == 0) ||
|
|
#ifdef IPCOM_USE_INET
|
|
(ipike_addr_copy(addr, (union Ip_sockaddr_union*)&ifreq.ip_ifr_addr) != IPIKE_SUCCESS) ||
|
|
#else
|
|
(ipike_addr_copy(addr, (union Ip_sockaddr_union*)&ifxreq.ifr_ifru.ifru_addr) != IPIKE_SUCCESS) ||
|
|
#endif
|
|
ipike_addr_is_zero(addr))
|
|
{
|
|
IPCOM_LOG0(ERR, "ipike_get_if_addr: failed to get address");
|
|
}
|
|
else
|
|
{
|
|
found_address = IP_TRUE;
|
|
}
|
|
ipcom_socketclose(s);
|
|
}
|
|
}
|
|
ipcom_if_freenameindex(ni);
|
|
}
|
|
|
|
return found_address;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_add_delete_address
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_add_delete_address(
|
|
Ip_bool add,
|
|
const char *ifname,
|
|
union Ip_sockaddr_union *addr,
|
|
union Ip_sockaddr_union *netmask)
|
|
{
|
|
Ipike_error err = IPIKE_FAILED;
|
|
|
|
if (addr != IP_NULL)
|
|
{
|
|
#ifdef IPCOM_USE_INET
|
|
if (addr->sa.sa_family == IP_AF_INET)
|
|
{
|
|
if (netmask == IP_NULL)
|
|
err = ipike_add_delete_ipv4_address(add, ifname, &addr->sin, IP_NULL);
|
|
else
|
|
err = ipike_add_delete_ipv4_address(add, ifname, &addr->sin, &netmask->sin);
|
|
}
|
|
#endif
|
|
#ifdef IPCOM_USE_INET6
|
|
if (addr->sa.sa_family == IP_AF_INET6)
|
|
{
|
|
if (netmask == IP_NULL)
|
|
err = ipike_add_delete_ipv6_address(add, ifname, &addr->sin6, IP_NULL);
|
|
else
|
|
err = ipike_add_delete_ipv6_address(add, ifname, &addr->sin6, &netmask->sin6);
|
|
}
|
|
#endif
|
|
IPCOM_LOG3(DEBUG2, "%s address %s %s",
|
|
add ? "Add" : "Delete",
|
|
ipike_addr_to_str(addr),
|
|
(err == IPIKE_SUCCESS) ? "succeeded" : "failed");
|
|
|
|
}
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_validate_str
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ipike_error
|
|
ipike_validate_str(const char *input_str, char *ctx)
|
|
{
|
|
(void)ctx;
|
|
|
|
if (input_str == IP_NULL || *input_str == IP_NULL
|
|
|| IP_NULL != ipcom_strchr(input_str,'{')
|
|
|| IP_NULL != ipcom_strchr(input_str,'}')
|
|
|| IP_NULL != ipcom_strchr(input_str,';'))
|
|
{
|
|
IPCOM_LOG2(ERR, "Bad configuration, invalid config value '%s'='%s'", ctx, input_str ? input_str : "(null)");
|
|
return IPIKE_FAILED;
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
|
|
|
|
#ifdef IP_DEBUG
|
|
/* Suppress prototype warnings */
|
|
IP_GLOBAL Ipike_error ipike_test_v6_increment(void);
|
|
|
|
IP_GLOBAL Ipike_error
|
|
ipike_test_v6_increment(void)
|
|
{
|
|
union Ip_sockaddr_union addr,mask;
|
|
int prefix = 0;
|
|
int safecount = 0;
|
|
|
|
for (prefix = 64; prefix <= 128 ; prefix += 32)
|
|
{
|
|
switch (prefix)
|
|
{
|
|
case 32:
|
|
(void)ipike_addr_load_subnet("2000:0000:ffff:ffff:ffff:ffff:ffff:ff00/128",&addr,&mask);
|
|
break;
|
|
case 64:
|
|
(void)ipike_addr_load_subnet("2000:0000:0000:0000:ffff:ffff:ffff:ff00/128",&addr,&mask);
|
|
break;
|
|
case 96:
|
|
(void)ipike_addr_load_subnet("2000:0000:0000:0000:0000:0000:ffff:ff00/128",&addr,&mask);
|
|
break;
|
|
case 128:
|
|
(void)ipike_addr_load_subnet("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00/128",&addr,&mask);
|
|
break;
|
|
default:
|
|
(void)ipike_addr_load_subnet("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128",&addr,&mask);
|
|
break;
|
|
}
|
|
|
|
ipcom_printf(" Testing for prefix %d addr %s \n",prefix, ipike_addr_to_str(&addr));
|
|
|
|
while (ipike_addr_increment_v6(&addr, prefix) != IPIKE_FAILED && (safecount < 1000000))
|
|
{
|
|
if (!(safecount % 10000))
|
|
ipcom_printf("Incremented address is %s \n",ipike_addr_to_str(&addr));
|
|
safecount++;
|
|
}
|
|
safecount = 0;
|
|
ipcom_printf("Failed to increment address : %s \n",ipike_addr_to_str(&addr));
|
|
ipcom_printf("-------------------------------------------------\n\n");
|
|
|
|
}
|
|
|
|
return IPIKE_SUCCESS;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_is_any_addr
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipike_addr_is_any(union Ip_sockaddr_union* addr)
|
|
{
|
|
#if defined(IPCOM_USE_INET)
|
|
if (addr->sin.sin_family == IP_AF_INET)
|
|
return ( addr->sin.sin_addr.s_addr == IP_INADDR_ANY );
|
|
#endif
|
|
#if defined(IPCOM_USE_INET6)
|
|
if ( addr->sin6.sin6_family == IP_AF_INET6 )
|
|
return IP_IN6_ARE_ADDR_EQUAL(&addr->sin6.sin6_addr, &ip_in6addr_any);
|
|
#endif
|
|
|
|
/* Should not happen */
|
|
return IP_FALSE;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_addr_is_host_mask
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipike_addr_is_host_mask(union Ip_sockaddr_union* addr)
|
|
{
|
|
Ip_u8* p;
|
|
Ip_u32 n;
|
|
|
|
p = ipike_addr_get_ptr(addr);
|
|
n = ipike_addr_get_len(addr);
|
|
while (n > 0)
|
|
if (p[--n] != 0xff)
|
|
return IP_FALSE;
|
|
|
|
return IP_TRUE;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_util_str_is_hex
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_bool
|
|
ipike_util_str_is_hex(const char *str)
|
|
{
|
|
const char *c;
|
|
|
|
if ( ipcom_strncmp(str, "0x", 2) )
|
|
return IP_FALSE;
|
|
|
|
c = str + 2;
|
|
|
|
if ( *c == '\0' )
|
|
return IP_FALSE;
|
|
|
|
for (; *c; c++)
|
|
{
|
|
if ( !ipcom_isxdigit((int)*c) )
|
|
return IP_FALSE;
|
|
}
|
|
|
|
return IP_TRUE;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_util_str_hex2bin
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL Ip_u8*
|
|
ipike_util_str_hex2bin(const char *str, Ip_size_t *len)
|
|
{
|
|
Ip_u8 *ret;
|
|
|
|
if (!str || !len)
|
|
return IP_NULL;
|
|
|
|
/* Remove '0x' prefix */
|
|
*len = ipcom_strlen(str) - 2;
|
|
|
|
ret = ipike_hex2bin(str + 2 , len);
|
|
|
|
if ( ret == IP_NULL )
|
|
*len = 0;
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_time_diff
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL long
|
|
ipike_time_diff_sec(
|
|
const struct Ip_timeval * t1,
|
|
const struct Ip_timeval * t2)
|
|
{
|
|
struct Ip_timeval diff;
|
|
|
|
ip_timeval_sub(t1, t2, &diff);
|
|
|
|
return (long)(diff.tv_sec + ((diff.tv_usec + 500000)/ 1000000));
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipike_time
|
|
*===========================================================================
|
|
*/
|
|
IP_GLOBAL long
|
|
ipike_time(void)
|
|
{
|
|
struct Ip_timeval now;
|
|
|
|
ipcom_microtime(&now);
|
|
|
|
return (long)(now.tv_sec + ((now.tv_usec + 500000) / 1000000));
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|