Files
freeswitch/libs/sipcc/core/src-common/util_string.c
T
2012-12-17 20:15:23 -05:00

367 lines
8.2 KiB
C

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <errno.h>
#include <limits.h>
#include "cpr_types.h"
#include "cpr_stdio.h"
#include "cpr_stdlib.h"
#include "cpr_socket.h"
#include "cpr_in.h"
#include "util_string.h"
/*
* Conver IP address into dotted format or colon format.
*
* @param addr_str : string to hold IP
* addr : pointer to the IP address
*
* @return none
*
* @pre none
*
*/
void
ipaddr2dotted (char *addr_str, cpr_ip_addr_t *addr)
{
if (addr_str)
{
switch (addr->type) {
case CPR_IP_ADDR_IPV4 :
sprintf(addr_str, "%u.%u.%u.%u",
(addr->u.ip4 >> 24) & 0xFF,
(addr->u.ip4 >> 16) & 0xFF,
(addr->u.ip4 >> 8) & 0xFF,
(addr->u.ip4) & 0xFF);
break;
case CPR_IP_ADDR_IPV6:
sprintf(addr_str, "[%x:%x:%x:%x:%x:%x:%x:%x]",
(addr->u.ip6.addr.base16[7]),
(addr->u.ip6.addr.base16[6]),
(addr->u.ip6.addr.base16[5]),
(addr->u.ip6.addr.base16[4]),
(addr->u.ip6.addr.base16[3]),
(addr->u.ip6.addr.base16[2]),
(addr->u.ip6.addr.base16[1]),
(addr->u.ip6.addr.base16[0]));
break;
default:
break;
}
}
}
/*
* Convert IP address to appropriate format dotted,or with colon
*
* @param addr_str ip address string
*
* @return address
*
* @pre none
*
*/
uint32_t
dotted2ipaddr (const char *addr_str)
{
uint32_t address = 0;
const char *p = NULL;
char section_str[3];
int sections[4];
int section;
int i;
long strtoul_result;
char *strtoul_end;
/* Check args */
if ((!addr_str) || (addr_str[0] == '\0'))
{
return 0xFFFFFFFF;
}
/* Init */
for (i = 0; i < 4; i++)
{
sections[i] = 0;
}
p = addr_str;
/* Remove leading blanks */
while ((*p == ' ') || (*p == '\t') || (*p == '\n') || (*p == '\r'))
{
p++;
}
for (section = 0; section < 4; section++)
{
i = 0;
section_str[0] = '\0';
section_str[1] = '\0';
section_str[2] = '\0';
while ((*p != '.') && (i < 3)) {
section_str[i] = *p;
i++;
p++;
}
errno = 0;
strtoul_result = strtoul(section_str, &strtoul_end, 10);
if (errno || section_str == strtoul_end ||
strtoul_result > 255) {
return 0xFFFFFFFF;
}
sections[section] = (int) strtoul_result;
address = address | (sections[section]<<((3-section)*8));
p++;
}
return address;
}
/*
* ntohl function wrapper for both IPv4 and Ipv6
*
* @param ip_addr_in, ip_addr_out : IP addresses
*
* @return none
*
* @pre none
*
*/
void util_ntohl (cpr_ip_addr_t *ip_addr_out, cpr_ip_addr_t *ip_addr_in)
{
int i,j;
unsigned char tmp;
ip_addr_out->type = ip_addr_in->type;
if (ip_addr_in->type == CPR_IP_ADDR_IPV4) {
ip_addr_out->u.ip4 = ntohl(ip_addr_in->u.ip4);
} else {
//to do IPv6: Add ntohl functionality for ipv6.
if (ip_addr_out == ip_addr_in) {
for (i=0, j=15; i<8; i++, j--) {
tmp = ip_addr_out->u.ip6.addr.base8[j];
ip_addr_out->u.ip6.addr.base8[j] = ip_addr_in->u.ip6.addr.base8[i];
ip_addr_in->u.ip6.addr.base8[i] = tmp;
}
} else {
for (i=0, j=15; i<16; i++, j--) {
ip_addr_out->u.ip6.addr.base8[j] = ip_addr_in->u.ip6.addr.base8[i];
}
}
}
}
/*
* Check if the IP address passed is valid. For IPv4& IPv6 check if value 0 if so
* return FALSE. If the type is CPR_IP_ADDR_INVALID or any other non defined type
* return FALSE.
*
*
* @param ip_addr IP address
*
* @return boolean False if not a valid IP, or else true
*
* @pre none
*
*/
boolean util_check_if_ip_valid (cpr_ip_addr_t *ip_addr)
{
if (ip_addr->type == CPR_IP_ADDR_INVALID) {
return(FALSE);
}
if (ip_addr->type == CPR_IP_ADDR_IPV4 &&
ip_addr->u.ip4 == 0) {
return(FALSE);
}
if ((ip_addr->type == CPR_IP_ADDR_IPV6) &&
(ip_addr->u.ip6.addr.base16[7] == 0) &&
(ip_addr->u.ip6.addr.base16[6] == 0) &&
(ip_addr->u.ip6.addr.base16[5] == 0) &&
(ip_addr->u.ip6.addr.base16[4] == 0) &&
(ip_addr->u.ip6.addr.base16[3] == 0) &&
(ip_addr->u.ip6.addr.base16[2] == 0) &&
(ip_addr->u.ip6.addr.base16[1] == 0) &&
(ip_addr->u.ip6.addr.base16[0] == 0)) {
return(FALSE);
}
if ((ip_addr->type != CPR_IP_ADDR_INVALID) &&
(ip_addr->type != CPR_IP_ADDR_IPV4) &&
(ip_addr->type != CPR_IP_ADDR_IPV6)) {
return(FALSE);
}
return(TRUE);
}
/*
* Compare 2 IP addresses
*
* @param ip_addr1 & ip_addr2 2 ip addresses to compare
*
* @return true if that matches or else false
*
* @pre (ip_addr1 != NULL) && (ip_addr2 != NULL)
*
*/
boolean util_compare_ip (cpr_ip_addr_t *ip_addr1, cpr_ip_addr_t *ip_addr2)
{
if (ip_addr1->type != ip_addr2->type) {
return(FALSE);
}
if (ip_addr1->type == CPR_IP_ADDR_IPV4 &&
ip_addr2->type == CPR_IP_ADDR_IPV4) {
return((boolean) (ip_addr1->u.ip4 == ip_addr2->u.ip4));
} else if (ip_addr1->type == CPR_IP_ADDR_IPV6 &&
ip_addr2->type == CPR_IP_ADDR_IPV6) {
return((boolean)memcmp((void *)&(ip_addr1->u.ip6.addr.base8),
(void *)&(ip_addr2->u.ip6.addr.base8), 16));
}
return(FALSE);
}
/*
* Extract ip address information from socket storage structure
*
* @param ip_addr ip address to be filled.
* cpr_sockaddr_storage storage structure pointer
*
* @return none
*
* @pre (ip_addr != NULL)
*
*/
void util_extract_ip (cpr_ip_addr_t *ip_addr,
cpr_sockaddr_storage *from)
{
switch (from->ss_family) {
case AF_INET6:
ip_addr->type = CPR_IP_ADDR_IPV6;
ip_addr->u.ip6 = ((cpr_sockaddr_in6_t *)from)->sin6_addr;
break;
case AF_INET:
ip_addr->type = CPR_IP_ADDR_IPV4;
ip_addr->u.ip4 = ((cpr_sockaddr_in_t *)from)->sin_addr.s_addr;
break;
default:
break;
}
}
/*
* Get port number from storage structure.
*
* @param sock_storage
*
* @return port number
*
* @pre (sock_storage != NULL)
*
*/
uint16_t util_get_port (cpr_sockaddr_storage *sock_storage)
{
switch (sock_storage->ss_family) {
case AF_INET6:
return(((cpr_sockaddr_in6_t *)sock_storage)->sin6_port);
case AF_INET:
return(((cpr_sockaddr_in_t *)sock_storage)->sin_port);
default:
break;
}
return(0);
}
void util_get_ip_using_mode (cpr_ip_addr_t *ip_addr, cpr_ip_mode_e ip_mode,
uint32_t ip4, char *ip6)
{
*ip_addr = ip_addr_invalid;
switch (ip_mode) {
case CPR_IP_MODE_IPV4:
ip_addr->type = CPR_IP_ADDR_IPV4;
ip_addr->u.ip4 = ip4;
break;
case CPR_IP_MODE_IPV6:
ip_addr->type = CPR_IP_ADDR_IPV6;
if (ip6 != NULL) {
memcpy((void *)&(ip_addr->u.ip6.addr.base8[16]), (void *)ip6, 16);
}
break;
case CPR_IP_MODE_DUAL:
default:
break;
}
}
unsigned long
gmt_string_to_seconds (char *gmt_string, unsigned long *seconds)
{
char *token;
// Do a preliminary check and see if the string
// passed in is a completely numeric string
// If it is, then we will return just that number
// and return a 1 for the error code, meaning
// we parsed a
*seconds = strtoul(gmt_string, &token, 10);
if ((token == NULL) || (token[0] == '\0')) {
return 1;
}
*seconds = 0;
return 0;
}
long
diff_current_time (unsigned long t1, unsigned long *difference)
{
*difference = 1;
return 0;
}
boolean
is_empty_str (char *str)
{
if (str == NULL) {
return TRUE;
}
if (strncmp(str, EMPTY_STR, EMPTY_STR_LEN) == 0) {
return TRUE;
}
return FALSE;
}
void
init_empty_str (char *str)
{
strcpy(str,EMPTY_STR);
}