📄 dns.c
字号:
/* The name was resolved. Add this host to the cache. The only reason
this addition can fail is if there is no memory. */
l_host = DNS_Add_Host(name, addr, ttl);
if (l_host == NU_NULL)
{
status = NU_NO_MEMORY;
}
else
{
status = NU_SUCCESS;
*host = l_host;
}
}
}
#endif /* INCLUDE_DNS == NU_TRUE */
return (status);
} /* DNS_Find_Host_By_Addr */
#if (INCLUDE_DNS == NU_TRUE)
/*****************************************************************************
* FUNCTION
*
* DNS_Resolve
*
* DESCRIPTION
*
* This routine will handle domain based name lookup. It can hadle both
* queries for names and quiries for IP addresses. Either the name and ttl
* are returned or an IP address and ttl are returned.
*
* INPUTS
*
* name A host name.
* ip_addr The host IP address, filled in by this
* function.
* ttl Time To Live, length of time the host info.
* can be cached. Filled in here.
* type Type of query, name or address.
*
* OUTPUTS
*
* NU_SUCCESS Indicates successful operation.
* NU_DNS_ERROR or -1 Indicates failure.
* NU_NO_DNS_SERVER No DNS servers have been registered with the
* stack.
*
******************************************************************************/
STATUS DNS_Resolve(CHAR *name, CHAR *ip_addr, UNSIGNED *ttl, UINT16 type)
{
STATUS stat;
CHAR *buffer;
INT q_size;
DNS_SERVER *cur_server;
/* Is there at least one DNS Server. */
if ( !(*(UINT32 *)DNS_Servers.dnss_head->dnss_ip))
{
return (NU_NO_DNS_SERVER);
}
/* Build the DNS query. */
switch (type)
{
case DNS_TYPE_A :
if ((q_size = DNS_Build_Query(name, (VOID **)&buffer, type)) < 0)
return -1;
break;
case DNS_TYPE_PTR :
if ((q_size = DNS_Build_Query(ip_addr, (VOID **)&buffer, type)) < 0)
return -1;
break;
default:
return -1;
}
/* Loop through the list of DNS servers querying them until the query
is successful or until we exhaust the list (spr474). */
for( cur_server = DNS_Servers.dnss_head;
cur_server && ((UINT32 *)cur_server->dnss_ip)[0] != 0;
cur_server = cur_server->dnss_next)
{
/* Query the DNS server. Upon returning the buffer will contain the
response to our query. */
if (DNS_Query(buffer, q_size, cur_server->dnss_ip) > 0)
break;
}
/* If we stepped through every entry in the list or if we stepped through
every used entry then return failure. */
if ((cur_server == NU_NULL) || (*(UINT32 *)cur_server->dnss_ip == 0))
{
/* Return the buffer to the memory pool. */
NU_Deallocate_Memory(buffer);
/* Return error */
return -1;
}
/* Now process the response. */
switch (type)
{
case DNS_TYPE_A :
stat = DNS_Extract_Data ((DNS_PKT_HEADER *)buffer, ip_addr, ttl,
(INT)type);
break;
case DNS_TYPE_PTR :
stat = DNS_Extract_Data ((DNS_PKT_HEADER *)buffer, name, ttl, (INT)type);
break;
default:
return -1;
}
/* Deallocate the memory buffer. */
NU_Deallocate_Memory(buffer);
if (stat != NU_SUCCESS)
return (NU_DNS_ERROR);
else
return (stat);
} /* DNS_Resolve */
/****************************************************************************
* FUNCTION
*
* DNS_Build_Query
*
* DESCRIPTION
*
* This function will build a DNS query packet.
*
* INPUTS
*
* data
* buffer A pointer to a buffer pointer.
* type A query type.
*
* OUTPUTS
*
* INT:
* > 0 The size of the packed name.
* NU_MEM_ALLOC
* < 0 General failure
*
******************************************************************************/
INT DNS_Build_Query(CHAR *data, VOID **buffer, UINT16 type)
{
DNS_PKT_HEADER *dns_pkt;
CHAR *ptr;
DNS_RR *rr_ptr;
INT name_size;
CHAR name[80];
/* Allocate a block of memeory to build the query packet in. */
if (NU_Allocate_Memory (&System_Memory, (VOID **)&dns_pkt,
DNS_MAX_MESSAGE_SIZE, NU_NO_SUSPEND) != NU_SUCCESS)
{
return (NU_NO_MEMORY);
}
/* Setup the packet. */
PUT16(dns_pkt, DNS_ID_OFFSET, 1);
PUT16(dns_pkt, DNS_FLAGS_OFFSET, DNS_RD); /* Set the Recursion desired bit. */
PUT16(dns_pkt, DNS_QDCOUNT_OFFSET, 1); /* There is only one query. */
PUT16(dns_pkt, DNS_ANCOUNT_OFFSET, 0);
PUT16(dns_pkt, DNS_NSCOUNT_OFFSET, 0);
PUT16(dns_pkt, DNS_ARCOUNT_OFFSET, 0);
/* Point to the query section of the packet. */
ptr = (CHAR *)(dns_pkt + 1);
/* If we have a IP address and trying to get a name, convert the address to
a character string. */
if (type == DNS_TYPE_PTR)
DNS_Addr_To_String(data, name);
/* Pack the domain name, i.e., put it in a format the server will
understand. The packed domain name will be copied into the location
pointer to by q_ptr. */
switch (type)
{
case DNS_TYPE_A :
if ((name_size = DNS_Pack_Domain_Name(ptr, data)) < 0 )
{
NU_Deallocate_Memory(dns_pkt);
return (name_size);
}
break;
case DNS_TYPE_PTR :
if ((name_size = DNS_Pack_Domain_Name(ptr, name)) < 0)
{
NU_Deallocate_Memory(dns_pkt);
return (name_size);
}
break;
default :
NU_Deallocate_Memory(dns_pkt);
return NU_INVALID_PARM;
}
/* Move the pointer past the end of the name. */
rr_ptr = (DNS_RR *)(ptr + name_size);
/* Load the type and class fields of the query structure. */
PUT16(rr_ptr, DNS_TYPE_OFFSET, type);
PUT16(rr_ptr, DNS_CLASS_OFFSET, DNS_CLASS_IN);
/* The ttl and rdlength are not needed for a query. Set them to zero. */
PUT32(rr_ptr, DNS_TTL_OFFSET, 0);
PUT16(rr_ptr, DNS_RDLENGTH_OFFSET, 0);
/* Return a pointer to the DNS packet. */
*buffer = dns_pkt;
return (sizeof(DNS_PKT_HEADER) + name_size + 4);
} /* DNS_Build_Query */
/****************************************************************************
* FUNCTION
*
* DNS_Query
*
* DESCRIPTION
*
* This function queries a DNS server. It sends a DNS query packet and
* waits for the response.
*
* INPUTS
*
* buffer A pointer to a buffer containing a query pkt.
* q_size The size of the query.
* dns_server
*
* OUTPUTS
*
* INT:
* > 0 The size of the received response.
* NU_FAILED_QUERY
* < 0 General failure.
*
******************************************************************************/
INT DNS_Query(CHAR *buffer, INT q_size, UINT8 *dns_server)
{
struct addr_struct dns_addr;
FD_SET readfs, writefs, exceptfs;
STATUS stat;
INT attempts = DNS_MAX_ATTEMPTS;
STATUS r_size = 0;
INT32 bytes_sent;
INT socketd;
if ((socketd = NU_Socket(NU_FAMILY_IP, NU_TYPE_DGRAM, 0)) < 0)
return (socketd);
/* Fill in a structure with the server address */
dns_addr.family = NU_FAMILY_IP;
dns_addr.port = DNS_PORT;
*(UINT32 *)dns_addr.id.is_ip_addrs = IP_ADDR(dns_server);
dns_addr.name = "";
/* Initially all the bits should be cleared. */
NU_FD_Init(&readfs);
while (attempts)
{
/* Send the DNS query. */
bytes_sent = NU_Send_To(socketd, buffer, (UINT16)q_size, 0, &dns_addr, 0);
/* If the data was not sent, we have a problem. */
if (bytes_sent < 0)
break;
/* Decrement the number of attempts left. */
attempts--;
/* Specify which socket we want to select on. */
NU_FD_Set(socketd, &readfs);
/* Select on the specified socket for one second. */
stat = NU_Select(NSOCKETS, &readfs, &writefs, &exceptfs,
SCK_Ticks_Per_Second);
/* If there is no data on the socket, either send the query again or
give up. */
if (stat != NU_SUCCESS)
continue;
/* Go get the server's response. */
r_size = (INT)NU_Recv_From(socketd, buffer, 1000, 0, &dns_addr, 0);
break;
}
/* Close the socket. */
NU_Close_Socket(socketd);
if (r_size > 0)
return r_size;
else
return (NU_FAILED_QUERY);
} /* DNS_Query */
/****************************************************************************
* FUNCTION
*
* DNS_Pack_Domain_Name
*
* DESCRIPTION
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -