0
mirror of https://github.com/Indemsys/Frequency_Inverter.git synced 2026-05-12 14:28:29 +00:00
Files
2022-01-04 12:22:53 +02:00

1079 lines
33 KiB
C

/**HEADER********************************************************************
*
* Copyright (c) 2008 Freescale Semiconductor;
* All Rights Reserved
*
* Copyright (c) 2004-2008 Embedded Access Inc.;
* All Rights Reserved
*
* Copyright (c) 1989-2008 ARC International;
* All Rights Reserved
*
***************************************************************************
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL FREESCALE OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************
*
* $FileName: dnsutil.c$
* $Version : 3.5.14.0$
* $Date : Jan-20-2010$
*
* Comments:
*
* This file contains the functions used exclusively by the
* user interface functions RTCS_gethostbyname,
* DNS_gethostbyname, and DNS_gethostbyaddr for RTCS.
*
*END************************************************************************/
#include <rtcs.h>
#include "rtcs_prv.h"
#if RTCSCFG_ENABLE_UDP
#if RTCSCFG_ENABLE_DNS
#include <ctype.h>
#include <string.h>
#include <fio.h>
#include "dns.h"
/*
GCC compiler did not have ctype in libc.
Used these definitions to resolve the problem:
#define tolower(c) (((c) >= 'A' && (c) <= 'Z') ? (c)-'A'+'a' : (c))
#define isalpha(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
#define isdigit(c) ( (c) >= '0' && (c) <= '9' )
#define isalnum(c) (isalpha(c) || isdigit(c))
*/
/* Global variable used for gethostbyaddr and gethostbyname calls */
static INTERNAL_HOSTENT_STRUCT RTCS_HOST;
static uchar RTCS_HOST_NAMES[DNS_MAX_NAMES][DNS_MAX_CHARS_IN_NAME];
static _ip_address RTCS_HOST_ADDRS[DNS_MAX_ADDRS];
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : DNS_is_dotted_IP_addr()
* Returned Value : char _PTR_
* Comments :
*
*END*-----------------------------------------------------------------*/
uint_32 DNS_is_dotted_IP_addr
(
uchar _PTR_ name,
uchar _PTR_ fill_buffer_ptr
)
{ /* Body */
uint_32 i;
uint_32 j = 0;
uint_32 k;
uint_32 size = 0;
uint_32 digit_count = 0;
uint_32 dot_count = 0;
int_32 byte_num;
uint_32 addr_number = 0;
uchar number_chars[4];
uchar actual_number;
uchar addr[4][3];
uchar _PTR_ number_buffer_ptr;
uchar appended_name[12] = {"in-addr.arpa"};
boolean leading_zero;
/*
** first check to see if name is written in correct dotted decimal
** IP address format
*/
for (i=0; name[i] != '\0'; ++i ) {
if ( name[i] == '.' ) {
dot_count++;
if ( dot_count > 3 ) {
/* invalid IP address */
return( RTCSERR_DNS_INVALID_IP_ADDR );
}/* Endif */
if ( digit_count == 0 ) {
/* there are no digits before the '.' */
return( RTCSERR_DNS_INVALID_IP_ADDR );
}/* Endif */
byte_num = byte_num / 10; /* shift back */
if ( (byte_num < 0 ) || (byte_num > 255) ) {
/* if the number does fall within this range it's invalid */
return( RTCSERR_DNS_INVALID_IP_ADDR );
} else {
addr_number++;
number_chars[j] = digit_count;
j++;
digit_count = 0;
} /* Endif */
} else { /* a digit */
if ( digit_count == 0 ) {
byte_num = 0;
}/* Endif */
++digit_count;
if ( digit_count > 3 ) {
/* too many digits between the '.' */
return( RTCSERR_DNS_INVALID_IP_ADDR );
}/* Endif */
if ( isdigit(name[i]) ) {
/* number is in range */
addr[addr_number][digit_count - 1] = name[i];
byte_num = byte_num + name[i] - '0';
byte_num = byte_num * 10;
} else {
/* if the characters are not decimal digits it's invalid */
return( RTCSERR_DNS_INVALID_IP_ADDR );
}/* Endif */
}/* Endif */
} /* Endfor */
if ( digit_count == 0 ) {
/* there are no digits after the last '.' */
return( RTCSERR_DNS_INVALID_IP_ADDR );
} /* Endif */
byte_num = byte_num / 10;
if ( (byte_num < 0 ) || (byte_num > 255) ) {
/* if the number does fall within this range it's invalid */
return( RTCSERR_DNS_INVALID_IP_ADDR );
} else {
number_chars[j] = digit_count;
} /* Endif */
if ( dot_count != 3 ) {
/* the wrong number of dots were found */
return( RTCSERR_DNS_INVALID_IP_ADDR );
}/* Endif */
/*
** If we got this far, it's a legal IP addr, reverse the numbers,
** in the fill_buffer and append "in-addr.arpa" to it.
*/
for ( i = 0; i < 4; i++) {
leading_zero = FALSE;
number_buffer_ptr = fill_buffer_ptr;
actual_number = number_chars[j];
htonc(fill_buffer_ptr, number_chars[j]);
fill_buffer_ptr++;
size++;
for ( k = 0; k < number_chars[j]; k++ ) {
if ( addr[addr_number][k] == '0' ) {
if ( addr[addr_number][k] == '0' && k == 0 ) {
leading_zero = TRUE;
actual_number--;
continue;
} /* Endif */
if ( addr[addr_number][k] == '0' && k == 1
&& leading_zero == TRUE && k < number_chars[j] ) {
actual_number--;
continue;
} /* Endif */
if ( addr[addr_number][k] == '0' && k == 1
&& leading_zero == TRUE && k == number_chars[j] ) {
htonc(fill_buffer_ptr, addr[addr_number][k]);
fill_buffer_ptr++;
htonc(number_buffer_ptr, actual_number);
number_buffer_ptr++;
size++;
break;
}/* Endif */
} /* Endif */
htonc(fill_buffer_ptr, addr[addr_number][k]);
fill_buffer_ptr++;
size++;
} /* Endfor */
addr_number--;
j--;
} /* Endfor */
htonc(fill_buffer_ptr, 7);
fill_buffer_ptr++;
for ( i = 0; i < 7; i++) {
htonc(fill_buffer_ptr, appended_name[i]);
fill_buffer_ptr++;
} /* Endfor */
htonc(fill_buffer_ptr, 4);
fill_buffer_ptr++;
i++;
for ( ; i < 12; i++) {
htonc(fill_buffer_ptr, appended_name[i]);
fill_buffer_ptr++;
} /* Endfor */
/*
** Need to append '\0' to terminate a domain name properly.
** This signifies the ROOT domain
*/
htonc(fill_buffer_ptr, '\0');
return( DNS_OK );
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : DNS_insert_IP_query()
* Returned Value : uint_32
* Comments :
*
*END*-----------------------------------------------------------------*/
static uint_32 DNS_insert_IP_query
(
uchar _PTR_ name,
uchar _PTR_ fill_buffer_ptr
)
{ /* Body */
uchar my_buff[DNS_MAX_IP_STRING_SIZE];
sprintf((char _PTR_)my_buff,"%ld.%ld.%ld.%ld", (uint_32)name[0],
(uint_32)name[1], (uint_32)name[2], (uint_32)name[3]);
return(DNS_is_dotted_IP_addr(my_buff, fill_buffer_ptr));
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : DNS_append_local_name()
* Returned Value : char _PTR_
* Comments :
*
*END*-----------------------------------------------------------------*/
static uint_32 DNS_append_local_name
(
uchar _PTR_ qname_buffer,
uint_32 total_length
)
{ /* Body */
uint_32 local_name_length = 0;
uint_32 error;
uchar _PTR_ label_length_ptr;
uchar label_length = 0;
if ( DNS_Local_network_name[local_name_length] == '\0' ) {
return( RTCSERR_DNS_INVALID_LOCAL_NAME );
}/* Endif */
/* If the Local Network is the ROOT Domain Name */
if ( ( DNS_Local_network_name[local_name_length] == '.' )
&& ( DNS_Local_network_name[local_name_length + 1] == '\0' )) {
htonc((qname_buffer + total_length), '\0');
return( DNS_OK );
}/* Endif */
label_length_ptr = qname_buffer + total_length;
error = DNS_OK;
while ( DNS_Local_network_name[local_name_length] ) {
/*
** RFC 1035 says labels must start with a letter, but in practice
** some aren't
*/
if ( isalnum(DNS_Local_network_name[local_name_length]) ) {
htonc((qname_buffer + total_length + 1),
DNS_Local_network_name[local_name_length]);
total_length++;
local_name_length++;
label_length++;
} else {
error = RTCSERR_DNS_INVALID_LOCAL_NAME;
break;
} /* Endif */
while ( ( DNS_Local_network_name[local_name_length] != '.' ) &&
( DNS_Local_network_name[local_name_length] != '\0' ) ) {
/* Domain Name characters can only be letters, hyphens, or numbers */
if ( (isalnum(DNS_Local_network_name[local_name_length]) ||
DNS_Local_network_name[local_name_length] == '-' ) &&
total_length < DNS_MAX_CHARS_IN_NAME &&
label_length <= DNS_MAX_LABEL_LENGTH ) {
htonc((qname_buffer + total_length + 1),
DNS_Local_network_name[local_name_length]);
total_length++;
local_name_length++;
label_length++;
} else {
error = RTCSERR_DNS_INVALID_LOCAL_NAME;
break;
} /* Endif */
} /* Endwhile */
if ( error == RTCSERR_DNS_INVALID_LOCAL_NAME ) {
break;
}/* Endif */
htonc(label_length_ptr, label_length);
label_length = 0;
total_length++;
label_length_ptr = qname_buffer + total_length;
local_name_length++;
} /* Endwhile */
if ( error == DNS_OK ) {
/*
** Need to append '\0' to terminate domain name properly.
** This signifies the ROOT domain
*/
htonc(label_length_ptr, '\0');
}/* Endif */
return( error );
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : DNS_is_dotted_domain_name()
* Returned Value : uint_32
* Comments : Checks the DNS Domain Name passed to it to see if the
* proper naming conventions have been followed.
*
*END*-----------------------------------------------------------------*/
uint_32 DNS_is_dotted_domain_name
(
uchar _PTR_ domain_name,
uchar _PTR_ qname_buffer
)
{ /* Body */
uint_32 total_length = 0;
uint_32 error;
uchar _PTR_ label_length_ptr;
uchar label_length = 0;
if ( domain_name[total_length] == '\0' ) {
return( RTCSERR_DNS_INVALID_NAME );
}/* Endif */
/* If the request is for the ROOT Domain Name */
if ( ( domain_name[total_length] == '.' )
&& ( domain_name[total_length + 1] == '\0' )) {
htonc(qname_buffer, '\0');
return( DNS_OK );
}/* Endif */
label_length_ptr = qname_buffer;
error = DNS_OK;
while ( domain_name[total_length] != '\0' ) {
/*
** RFC 1035 says labels must start with a letter, but in practice
** some aren't
*/
if ( isalnum(domain_name[total_length]) ) {
htonc((qname_buffer + total_length + 1), domain_name[total_length]);
total_length++;
label_length++;
} else {
error = RTCSERR_DNS_INVALID_NAME;
break;
} /* Endif */
while ( ( domain_name[total_length] != '.') &&
( domain_name[total_length] != '\0' ) ) {
/* Domain Name characters can only be letters, hyphens, or numbers */
if ( (isalnum(domain_name[total_length]) ||
domain_name[total_length] == '-' ) &&
total_length < DNS_MAX_CHARS_IN_NAME &&
label_length <= DNS_MAX_LABEL_LENGTH ) {
htonc((qname_buffer + total_length + 1), domain_name[total_length]);
total_length++;
label_length++;
} else {
error = RTCSERR_DNS_INVALID_NAME;
break;
} /* Endif */
} /* Endwhile */
if ( error == RTCSERR_DNS_INVALID_NAME ) {
break;
}/* Endif */
htonc(label_length_ptr, label_length);
label_length = 0;
if ( domain_name[total_length] != '\0' ) {
label_length_ptr = qname_buffer + total_length + 1;
} else {
/* It's NULL, append the local network name */
error = DNS_append_local_name( qname_buffer, total_length + 1 );
return( error );
} /* Endif */
total_length++;
} /* Endwhile */
if ( error == DNS_OK ) {
/*
** Need to append '\0' to terminate domain name properly.
** This denotes the ROOT domain
*/
htonc(label_length_ptr, '\0');
}/* Endif */
return( error );
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : DNS_parse_answer_name_to_dotted_form()
* Returned Value : uchar _PTR_
* Comments :
*
*END*-----------------------------------------------------------------*/
static uchar _PTR_ DNS_parse_answer_name_to_dotted_form
(
uchar _PTR_ buffer_ptr,
uchar _PTR_ name,
uint_32 loc
)
{ /* Body */
uchar _PTR_ compressed_name;
uchar _PTR_ fill_ptr;
uchar label_size;
uint_32 i;
uint_16 new_location;
fill_ptr = RTCS_HOST_NAMES[loc];
_mem_zero(fill_ptr, DNS_MAX_CHARS_IN_NAME);
compressed_name = name;
while ( ntohc(compressed_name) != '\0' ) {
if ( ntohc(compressed_name) & DNS_COMPRESSED_NAME_MASK ) {
new_location = ntohs(compressed_name)
& DNS_COMPRESSED_LOCATION_MASK;
compressed_name = buffer_ptr + new_location;
}/* Endif */
label_size = ntohc(compressed_name);
compressed_name++;
for ( i = 0; i < label_size; i++ ) {
*fill_ptr++ = ntohc(compressed_name);
compressed_name++;
} /* Endfor */
if ( ntohc(compressed_name) != '\0' ) {
*fill_ptr++ = '.';
}/* Endif */
} /* Endwhile */
*fill_ptr = '\0';
return( RTCS_HOST_NAMES[loc] );
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : DNS_free_HOSTENT_STRUCT()
* Returned Value : void
* Comments :
*
*END*-----------------------------------------------------------------*/
void DNS_free_HOSTENT_STRUCT
(
HOSTENT_STRUCT _PTR_ host_ptr
)
{ /* Body */
/*
** This function is no longer needed, but the wrapper is left for
** backwards compatibility.
*/
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : DNS_parse_UDP_response()
* Returned Value : HOSTENT_STRUCT_PTR
* Comments : If answers were returned, this function will
* parse them into a HOSTENT_STRUCT
*
*END*-----------------------------------------------------------------*/
HOSTENT_STRUCT _PTR_ DNS_parse_UDP_response
(
uchar _PTR_ buffer_ptr,
uchar _PTR_ name_ptr,
uint_16 query_type
)
{ /* Body */
DNS_MESSAGE_HEADER_STRUCT _PTR_ message_head_ptr = NULL;
DNS_RESPONSE_RR_MIDDLE_STRUCT _PTR_ answer_middle;
INTERNAL_HOSTENT_STRUCT _PTR_ host_ptr = &RTCS_HOST;
uchar _PTR_ answer_ptr;
uchar _PTR_ answer_tail;
uchar _PTR_ temp_ptr;
uint_16 response_length, answer_type,
name_size, number_of_answers, num_queries;
uint_32 i, name_index = 0;
uint_32 j = 0;
uint_32 k = 0;
uint_32 buffer_size;
uint_32 _PTR_ addr_ptr;
boolean unknown_answer_type = FALSE;
message_head_ptr = (DNS_MESSAGE_HEADER_STRUCT _PTR_)buffer_ptr;
buffer_size = sizeof(DNS_MESSAGE_HEADER_STRUCT);
temp_ptr = buffer_ptr + sizeof( DNS_MESSAGE_HEADER_STRUCT );
/* Zero the global HOSTENT_STRUCT */
_mem_zero((char_ptr)host_ptr, sizeof(INTERNAL_HOSTENT_STRUCT));
/* Get the number of queries. */
num_queries = ntohs(message_head_ptr->QDCOUNT);
for (i = 0; i < num_queries; i++) {
name_size = 0;
while( (ntohc(temp_ptr) != '\0') &&
name_size < DNS_MAX_CHARS_IN_NAME ) {
name_size = name_size + ntohc(temp_ptr) + 1;
temp_ptr = temp_ptr + ntohc(temp_ptr) + 1;
} /* Endwhile */
/* To include the terminating NULL char */
name_size++;
buffer_size += (name_size + sizeof(DNS_MESSAGE_TAIL_STRUCT));
temp_ptr += (1 + sizeof(DNS_MESSAGE_TAIL_STRUCT));
} /* Endfor */
number_of_answers = ntohs(message_head_ptr->ANCOUNT);
if (number_of_answers > DNS_MAX_NAMES ) {
number_of_answers = DNS_MAX_NAMES;
} /* Endif */
host_ptr->HOSTENT.h_aliases = &host_ptr->ALIASES[0];
host_ptr->HOSTENT.h_addr_list = (char_ptr _PTR_)&host_ptr->ADDRESSES[0];
host_ptr->ADDRESSES[0] = NULL;
host_ptr->HOSTENT.h_name = NULL;
host_ptr->HOSTENT.h_length = sizeof( _ip_address );
for (i = 0; (i < number_of_answers) && (j < DNS_MAX_ADDRS) &&
(k < DNS_MAX_NAMES); i++ )
{
answer_ptr = temp_ptr;
name_size = 0;
while( (ntohc(temp_ptr) != '\0') &&
name_size < DNS_MAX_CHARS_IN_NAME &&
!(ntohc(temp_ptr) & DNS_COMPRESSED_NAME_MASK)) {
name_size += ntohc(temp_ptr);
temp_ptr += ntohc(temp_ptr) + 1;
} /* Endwhile */
if ( ntohc(temp_ptr) & DNS_COMPRESSED_NAME_MASK ) {
temp_ptr++;
}/* Endif */
temp_ptr++;
answer_middle = (DNS_RESPONSE_RR_MIDDLE_STRUCT _PTR_)temp_ptr;
response_length = ntohs(answer_middle->RDLENGTH);
answer_type = ntohs(answer_middle->TYPE);
temp_ptr += sizeof(DNS_RESPONSE_RR_MIDDLE_STRUCT);
answer_tail = temp_ptr;
temp_ptr += response_length;
switch ( answer_type ) {
case DNS_A:
if ( host_ptr->HOSTENT.h_name == NULL ) {
host_ptr->HOSTENT.h_name =
(char _PTR_)DNS_parse_answer_name_to_dotted_form(
buffer_ptr, answer_ptr, name_index );
name_index++;
} /* Endif */
RTCS_HOST_ADDRS[j] = ntohl((uchar_ptr)answer_tail);
/*
** j is used in case BOTH CNAME and A data is received. If CNAME
** answer is first, will write into wrong address space if using
** i.
*/
host_ptr->ADDRESSES[j] = &RTCS_HOST_ADDRS[j];
j++;
/*
** This is to assure that the first IP address used is the first
** one that was given
*/
host_ptr->IP_address = *host_ptr->ADDRESSES[0];
break;
case DNS_PTR:
if (query_type == DNS_PTR) {
if (host_ptr->HOSTENT.h_name != NULL) {
host_ptr->ALIASES[k] = host_ptr->HOSTENT.h_name;
k++;
} /* Endif */
host_ptr->HOSTENT.h_name =
(char _PTR_)DNS_parse_answer_name_to_dotted_form(
buffer_ptr, answer_tail, name_index );
name_index++;
addr_ptr = RTCS_mem_alloc_zero( sizeof( _ip_address ));
if ( addr_ptr == NULL ) {
RTCS_log_error(ERROR_DNS, RTCSERR_DNS_UNABLE_TO_ALLOCATE_MEMORY,
0, 0, 0);
return( NULL );
}/* Endif */
*addr_ptr = *((_ip_address _PTR_)name_ptr);
host_ptr->ADDRESSES[j] = addr_ptr;
j++;
host_ptr->IP_address = *host_ptr->ADDRESSES[0];
} else {
host_ptr->ALIASES[k] = (char _PTR_)
DNS_parse_answer_name_to_dotted_form( buffer_ptr,
answer_tail, name_index );
name_index++;
k++;
} /* Endif */
break;
case DNS_CNAME:
/* the k is used for ALIASES as the j is used for ADDRESSES */
host_ptr->ALIASES[k] = (char _PTR_)
DNS_parse_answer_name_to_dotted_form(
buffer_ptr, answer_tail, name_index );
name_index++;
k++;
break;
default:
unknown_answer_type = TRUE;
} /* Endswitch */
if ( unknown_answer_type == TRUE ) {
break;
}/* Endif */
host_ptr->ADDRESSES[j] = NULL;
host_ptr->ALIASES[k] = NULL;
host_ptr->HOSTENT.h_addrtype = ntohs(answer_middle->CLASS);
} /* Endfor */
if ( number_of_answers == 0 ) {
return( NULL );
} /* Endif */
return( &RTCS_HOST.HOSTENT );
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : DNS_query_resolver_task()
* Returned Value : HOSTENT_STRUCT _PTR_
* Comments :
*
*END*-----------------------------------------------------------------*/
HOSTENT_STRUCT _PTR_ DNS_query_resolver_task
(
uchar _PTR_ name,
uint_16 query_type
)
{ /* Body */
DNS_MESSAGE_HEADER_STRUCT _PTR_ message_head_ptr;
DNS_MESSAGE_TAIL_STRUCT _PTR_ message_tail_ptr;
HOSTENT_STRUCT _PTR_ host_ptr = NULL;
sockaddr_in addr;
uint_32 local_sock;
uint_32 qname_size;
uint_32 buffer_size;
uint_16 rlen;
int_32 temp_size;
int_32 error;
uchar _PTR_ temp_ptr;
uchar _PTR_ qname_ptr;
uchar _PTR_ buffer_ptr;
/*
** If the size of this buffer is changed, also change the buffer size
** in the recvfrom() call near the bottom of this function
*/
buffer_ptr = RTCS_mem_alloc_zero( DNS_MAX_UDP_MESSAGE_SIZE );
if ( buffer_ptr == NULL ) {
RTCS_log_error(ERROR_DNS, RTCSERR_DNS_UNABLE_TO_ALLOCATE_MEMORY,
0, 0, 0);
return( NULL );
}/* Endif */
_mem_set_type(buffer_ptr, MEM_TYPE_DNS_UDP_MESSAGE);
qname_ptr = buffer_ptr + sizeof( DNS_MESSAGE_HEADER_STRUCT );
if ( query_type == DNS_A ) {
error = DNS_is_dotted_domain_name( name, qname_ptr );
if ( error == RTCSERR_DNS_INVALID_NAME ||
error == RTCSERR_DNS_INVALID_LOCAL_NAME ) {
_mem_free(buffer_ptr);
return( NULL );
}/* Endif */
} else {
if ( query_type == DNS_PTR ) {
error = DNS_insert_IP_query( name, qname_ptr );
if ( error == RTCSERR_DNS_INVALID_IP_ADDR ) {
_mem_free(buffer_ptr);
return( NULL );
}/* Endif */
} else {
_mem_free(buffer_ptr);
return( NULL );
} /* Endif */
} /* Endif */
local_sock = socket(AF_INET, SOCK_DGRAM, 0);
if ( local_sock == RTCS_HANDLE_ERROR ) {
RTCS_log_error(ERROR_DNS, RTCSERR_DNS_UNABLE_TO_OPEN_SOCKET,
0, 0, 0);
_mem_free(buffer_ptr);
return( NULL );
}/* Endif */
/* Local address */
addr.sin_family = AF_INET;
addr.sin_port = 0;
addr.sin_addr.s_addr = INADDR_ANY;
error = bind(local_sock, &addr, sizeof(addr));
if (error != RTCS_OK) {
RTCS_log_error(ERROR_DNS, RTCSERR_DNS_UNABLE_TO_BIND_SOCKET,
0, 0, 0);
_mem_free(buffer_ptr);
return( NULL );
} /* Endif */
/* set up buffer for sending query. */
message_head_ptr = (DNS_MESSAGE_HEADER_STRUCT _PTR_)buffer_ptr;
htons(message_head_ptr->ID, 0);
htons(message_head_ptr->CONTROL, DNS_STANDARD_QUERY);
htons(message_head_ptr->QDCOUNT, DNS_SINGLE_QUERY);
htons(message_head_ptr->NSCOUNT, 0);
htons(message_head_ptr->ARCOUNT, 0);
htons(message_head_ptr->ANCOUNT, 0);
qname_size = strlen((char _PTR_)qname_ptr );
/* Need to include the last '\0' character as well */
qname_size++;
temp_ptr = buffer_ptr + sizeof( DNS_MESSAGE_HEADER_STRUCT )
+ qname_size;
message_tail_ptr = (DNS_MESSAGE_TAIL_STRUCT _PTR_)temp_ptr;
htons(message_tail_ptr->QTYPE, query_type);
htons(message_tail_ptr->QCLASS, DNS_IN);
buffer_size = sizeof(DNS_MESSAGE_HEADER_STRUCT) + qname_size
+ sizeof(DNS_MESSAGE_TAIL_STRUCT);
/* Remote address, DNS_Resolver currently uses port 1024 */
addr.sin_port = DNS_RESOLVER_PORT;
addr.sin_addr.s_addr = DNS_RESOLVER_IP_ADDR;
rlen = sizeof(addr);
/* Send the buffer to the resolver for making a query */
error = sendto(local_sock, buffer_ptr, buffer_size, 0, &addr, rlen);
if (error == RTCS_ERROR) {
shutdown(local_sock, FLAG_ABORT_CONNECTION);
RTCS_log_error(ERROR_DNS, RTCSERR_DNS_UNABLE_TO_SEND_QUERY,
0, 0, 0);
_mem_free(buffer_ptr);
return( NULL );
}/* Endif */
/* Get the response from the resolver, if none received, return NULL */
error = (uint_32)RTCS_selectset( &local_sock, 1, DNS_QUERY_TIMEOUT );
if ( !error || error == RTCS_ERROR ) {
shutdown(local_sock, FLAG_ABORT_CONNECTION);
RTCS_log_error(ERROR_DNS, RTCSERR_DNS_NO_RESPONSE_FROM_RESOLVER,
0, 0, 0);
_mem_free(buffer_ptr);
return( NULL );
} /* Endif */
temp_size = recvfrom(local_sock, buffer_ptr, DNS_MAX_UDP_MESSAGE_SIZE,
0, &addr, &rlen);
if ( temp_size == RTCS_ERROR ) {
shutdown(local_sock, FLAG_ABORT_CONNECTION);
RTCS_log_error(ERROR_DNS, RTCSERR_DNS_PACKET_RECEPTION_ERROR,
0, 0, 0);
_mem_free(buffer_ptr);
return( NULL );
}/* Endif */
host_ptr = DNS_parse_UDP_response(buffer_ptr, name, query_type);
shutdown(local_sock, FLAG_ABORT_CONNECTION);
_mem_free(buffer_ptr);
return( host_ptr );
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : DNS_check_local_host_file()
* Returned Value : HOSTENT_STRUCT_PTR
* Comments : Maps a host name to an IP address
*
*END*-----------------------------------------------------------------*/
HOSTENT_STRUCT_PTR DNS_check_local_host_file
(
uchar_ptr name
)
{ /* Body */
INTERNAL_HOSTENT_STRUCT_PTR host_ptr = &RTCS_HOST;
uint_32 i;
boolean name_found;
uint_32 num_aliases = 0;
uint_32 host_index = 0;
uint_32 digit_count = 0;
uint_32 dot_count = 0;
uint_32 name_size, name_index = 0;
int_32 byte_num;
boolean dotted_decimal;
uint_32 temp = 0;
/* zero memory for HOSTENT_STRUCT */
_mem_zero(host_ptr, sizeof(INTERNAL_HOSTENT_STRUCT));
host_ptr->HOSTENT.h_aliases = &host_ptr->ALIASES[0];
host_ptr->HOSTENT.h_addr_list = (char_ptr _PTR_)&host_ptr->ADDRESSES[0];
/* assign address type and length */
host_ptr->HOSTENT.h_addrtype = AF_INET;
host_ptr->HOSTENT.h_length = 4; /* IP addresses only used - 4 bytes */
/* check to see if name is written in dotted decimal IP format */
dotted_decimal = TRUE;
for (i=0; name[i] != '\0'; ++i ) {
if ( name[i] == '.' ) {
dot_count++;
if ( dot_count > 3 ) {
/* invalid IP address */
dotted_decimal = FALSE;
break;
}/* Endif */
if ( digit_count == 0 ) {
/* there are no digits before the '.' */
dotted_decimal = FALSE;
break;
}/* Endif */
digit_count = 0;
byte_num = byte_num / 10; /* shift back */
if ( (byte_num < 0 ) || (byte_num > 255) ) {
/* if the number does fall within this range it's invalid */
dotted_decimal = FALSE;
break;
} else {
temp = temp + byte_num;
temp = temp * 0x100;
}/* Endif */
} else { /* a digit */
if ( digit_count == 0 ) {
byte_num = 0;
}/* Endif */
++digit_count;
if ( digit_count > 3 ) {
/* too many digits between the '.' */
dotted_decimal = FALSE;
break;
}/* Endif */
if ( isdigit(name[i]) ) {
/* number is in range */
byte_num = byte_num + name[i] - '0';
byte_num = byte_num * 10;
} else {
/* if the characters are not decimal digits it's invalid */
dotted_decimal = FALSE;
break;
}/* Endif */
}/* Endif */
} /* Endfor */
if ( dotted_decimal ) { /* check last number */
if ( digit_count == 0 ) {
/* there are no digits before the '.' */
dotted_decimal = FALSE;
}/* Endif */
byte_num = byte_num / 10;
if ( (byte_num < 0 ) || (byte_num > 255) ) {
/* if the number does fall within this range it's invalid */
dotted_decimal = FALSE;
} else {
temp = temp + byte_num;
}/* Endif */
if ( dot_count != 3 ) {
/* the wrong number of dots were found */
dotted_decimal = FALSE;
}/* Endif */
}/* Endif */
if ( i == 0 ) {
/* no name string of first char was not a number */
dotted_decimal = FALSE;
}/* Endif */
_mem_zero(RTCS_HOST_NAMES[name_index], DNS_MAX_CHARS_IN_NAME);
if ( dotted_decimal == TRUE ) {
name_size = strlen((char _PTR_)name );
name_size++;
_mem_copy(name, RTCS_HOST_NAMES[name_index], name_size);
/* assign the hostent struct from the dotted decimal IP name */
host_ptr->HOSTENT.h_name = (char _PTR_)RTCS_HOST_NAMES[name_index];
host_ptr->ALIASES[num_aliases] = NULL;
host_ptr->IP_address = temp;
host_ptr->ADDRESSES[0] = &host_ptr->IP_address;
host_ptr->ADDRESSES[1] = NULL;
name_found = TRUE;
} else {
name_found = FALSE;
/* search for the name in the hosts structure */
while ( ((RTCS_Hosts_list[host_index]).ip_address != 0) && !name_found) {
/*end of list hasn't been reached*/
/* check the aliases for the name */
i = 0;
while ( ((RTCS_Hosts_list[host_index]).aliases[i] != NULL) &&
!name_found)
{
if ( strcmp((char _PTR_)(RTCS_Hosts_list[host_index]).aliases[i],
(char _PTR_)name) == 0 )
{
name_found = TRUE;
}/* Endif */
++i;
} /* Endwhile */
/* check the name field for the name */
if ( strcmp((char _PTR_)(RTCS_Hosts_list[host_index]).host_name,
(char _PTR_)name) == 0)
{
name_found = TRUE;
} /* Endif */
if (name_found == TRUE ) { /* host name was found */
name_size = strlen( (RTCS_Hosts_list[host_index]).host_name );
name_size++;
_mem_copy((RTCS_Hosts_list[host_index]).host_name,
RTCS_HOST_NAMES[name_index], name_size);
host_ptr->HOSTENT.h_name = (char _PTR_)RTCS_HOST_NAMES[name_index];
name_index++;
/* assign alias list */
while ( (num_aliases < MAX_HOST_ALIASES)
&& ((RTCS_Hosts_list[host_index]).aliases[num_aliases] != NULL)
&& (name_index < DNS_MAX_NAMES))
{
name_size =
strlen((RTCS_Hosts_list[host_index]).aliases[num_aliases]);
name_size++;
_mem_zero(RTCS_HOST_NAMES[name_index], DNS_MAX_CHARS_IN_NAME);
_mem_copy((RTCS_Hosts_list[host_index]).aliases[num_aliases],
RTCS_HOST_NAMES[name_index], name_size);
host_ptr->ALIASES[num_aliases] =
(char _PTR_)RTCS_HOST_NAMES[name_index];
name_index++;
num_aliases++;
} /* Endwhile */
host_ptr->ALIASES[num_aliases] = NULL;
/* assign addresses (in our case only one IP address is allowed) */
_mem_copy((_ip_address _PTR_)
&((RTCS_Hosts_list[host_index]).ip_address), &RTCS_HOST_ADDRS[0],
sizeof(_ip_address));
host_ptr->ADDRESSES[0] = (uint_32_ptr)&RTCS_HOST_ADDRS[0];
host_ptr->ADDRESSES[1] = NULL;
} /* Endif */
++host_index;
} /* Endwhile */
}/* Endif */
if ( !name_found ) {
return( NULL );
}/* Endif */
return( &host_ptr->HOSTENT );
}/* EndBody */
#endif
#endif
/* EOF */