📄 dns_client.c
字号:
//*------------------------------------------------------------------------------------------------
//* 文件名 : dns_clinet.c
//* 功能描述 : dns客户端
//* 作者 : 焦海波
//* 版本 : 0.1
//* 建立日期、时间 : 2006/08/10 15:23
//* 最近修改日期、时间 :
//* 修改原因 :
//*------------------------------------------------------------------------------------------------
//*------------------------------------------ 头文件 -----------------------------------------------
#include "/uCOS-II/ucos_ii.h"
#include "/LwIP/include/lwip/tcpip.h"
#include "/tools/converter.h"
#include "dns_client.h"
//*================================================================================================
//* 函 数 区
//*================================================================================================
//*------------------------------------------------------------------------------------------------
//* 函数名称 : __ilvPacketDNSQuest
//* 功能描述 : 封装DNS查询包
//* : <pszDN>[in] 指向域名的指针
//* : <s32DNLen>[in] 域名长度
//* : <pstPbuf>[in] 指向st_pbuf结构的指针,它这个结构保存要发送的DNS的查询包
//* 出口参数 : 无
//*------------------------------------------------------------------------------------------------
__inline void __ilvPacketDNSQuest(INT8S *pszDN, INT32S s32DNLen, ST_PBUF *pstPbuf)
{
ST_DNS_PACKET_HDR *__pstDNSPacket;
BST_ID_AND_FLAGS *__pbstIDAndFlags;
__pstDNSPacket = (ST_DNS_PACKET_HDR*)pstPbuf->payload;
__pstDNSPacket->u32IDAndFlags = 0x00000000;
__pbstIDAndFlags = &__pstDNSPacket->u32IDAndFlags;
__pbstIDAndFlags->bitID = 0x0608;
__pbstIDAndFlags->bitIsRD = 0x1;
__pstDNSPacket->u16QCount = 0x0100;
__pstDNSPacket->u16ACount = 0x0000;
__pstDNSPacket->u16AuthCount = 0x0000;
__pstDNSPacket->u16ARC = 0x0000;
memcpy((INT8U*)pstPbuf->payload + DNS_PACKET_HDR_LEN, pszDN, s32DNLen);
*((INT8U*)pstPbuf->payload + DNS_PACKET_HDR_LEN + s32DNLen) = 0x00;
*((INT8U*)pstPbuf->payload + DNS_PACKET_HDR_LEN + s32DNLen + 1) = DNS_PACKET_QUERY_TYPE;
*((INT8U*)pstPbuf->payload + DNS_PACKET_HDR_LEN + s32DNLen + 2) = 0x00;
*((INT8U*)pstPbuf->payload + DNS_PACKET_HDR_LEN + s32DNLen + 3) = DNS_PACKET_QUERY_CLASS;
}
//*------------------------------------------------------------------------------------------------
//* 函数名称 : __ilu32ParseRespDNSPacket
//* 功能描述 : 解析DNS服务器响应的数据包
//* 入口参数 : <pstPbuf>[in] 指向ST_NETBUF的指针
//* : <pu32IP>[in] 指向接收缓冲区(保存IP地址)的指针
//* : <s32DNlen>[in] 要查询域名的长度
//* 出口参数 : - DNS_OK : 查询成功
//* : - DNS_NOT_EXIST : 指定的域名不存在
//* : - DNS_OTHER : 未知错误
//*------------------------------------------------------------------------------------------------
__inline INT32U __ilu32ParseRespDNSPacket(ST_PBUF *pstPbuf, INT32U *pu32IP, INT32S s32DNLen)
{
ST_DNS_PACKET_HDR *__pstDNSPacket;
INT32U __u32Val;
BST_ID_AND_FLAGS *__pbstIDAndFlags;
void *__pvData;
INT16U __u16ACount, __u16AnswerDataLen, __u16Offset;
__pstDNSPacket = (ST_DNS_PACKET_HDR *)pstPbuf->payload;
__u32Val = __pstDNSPacket->u32IDAndFlags;
__pbstIDAndFlags = &__u32Val;
if(__pbstIDAndFlags->bitOptResult == 0)
{
__u16ACount = macHighToLowForWord(__pstDNSPacket->u16ACount);
__u16Offset = s32DNLen + 14;
while(__u16ACount > 0)
{
__pvData = (INT8U*)pstPbuf->payload + DNS_PACKET_HDR_LEN + __u16Offset;
__u16AnswerDataLen = macHighToLowForWord(*((__packed INT16U*)__pvData));
if((__u16AnswerDataLen == 4) && macHighToLowForWord(*((__packed INT16U*)((INT8U*)__pvData - 8))) == DNS_PACKET_QUERY_TYPE)
{
*pu32IP = *((__packed INT32U *)((INT8U*)__pvData + 2));
return DNS_OK;
}
__u16Offset += 12 + __u16AnswerDataLen;
__u16ACount--;
}
return DNS_OTHER;
}
else if(__pbstIDAndFlags->bitOptResult == 3)
{
return DNS_NOT_EXIST;
}
return DNS_OTHER;
}
//*------------------------------------------------------------------------------------------------
//* 函数名称 : __vDNSRecv
//* 功能描述 : 接收并解析DNS服务器响应的数据包,它是一个回调函数,由udp_recv()设置
//* 入口参数 : <pstArg>[in] 指向ST_RECV_FUN_ARG结构的指针,这个结构保存着该函数需要的入口参数
//* : <pstUDPPCB>[in] 指向ST_UDP_PCB结构的指针
//* : <pstPbuf>[in] 指向st_pbuf结构的指针,它保存着收到的内容
//* : <pstIP>[in] IP地址
//* : <u16Port>[in] 端口号
//* 出口参数 : - DNS_OK : 查询成功
//* : - DNS_NOT_EXIST : 指定的域名不存在
//* : - DNS_OTHER : 未知错误
//*------------------------------------------------------------------------------------------------
static void __vDNSRecv(ST_RECV_FUN_ARG *pstArg, ST_UDP_PCB *pstUDPPCB,
ST_PBUF *pstPbuf, ST_IP_ADDR *pstIP, INT16U u16Port)
{
if(pstPbuf != NULL)
{
pstArg->u32RtnCode = __ilu32ParseRespDNSPacket(pstPbuf, pstArg->pu32IP, pstArg->s32DNLen);
pbuf_free(pstPbuf);
}
}
//*------------------------------------------------------------------------------------------------
//* 函数名称 : __u32GetIP
//* 功能描述 : 查询DNS服务器,获取指定域名绑定的IP地址,这里只能使用协议栈直接接口实现,使用其提供
//* : 的API无法满足需求。如果接收DNS响应包使用netconn_recv函数非常容易阻塞系统,因为UDP
//* : 不可靠。
//* : <pstPbuf>[in] 指向st_pbuf结构的指针,它这个结构保存要发送的DNS的查询包
//* : <pu32IP>[in] 指向接收缓冲区(保存IP地址)的指针
//* : <s32DNLen>[in] 要查询的域名长度
//* : <u32DNSIP>[in] DNS服务器的IP地址
//* 出口参数 : - DNS_OK : 查询成功
//* : - DNS_NOT_EXIST : 指定的域名不存在
//* : - DNS_NOT_CONN : 无法连接指定的域名服务器(主、备服务器均不可用)
//* : - DNS_OTHER : 未知错误
//*------------------------------------------------------------------------------------------------
INT32U __u32GetIP(ST_PBUF *pstPbuf, INT32U *pu32IP, INT32S s32DNLen, INT32U u32DNSIP)
{
ST_IP_ADDR __stIPAddr;
ST_UDP_PCB *__pstUDPPCB;
ST_RECV_FUN_ARG __stRecvArg;
INT32S i, k = 0;
INT32U __u32RtnCode;
__pstUDPPCB = udp_new();
if(__pstUDPPCB == NULL)
return DNS_OTHER;
__stIPAddr.addr = htonl(u32DNSIP);
if(udp_connect(__pstUDPPCB, &__stIPAddr, DNS_PORT) != ERR_OK)
return DNS_OTHER;
memset(&__stRecvArg, 0, sizeof(ST_RECV_FUN_ARG));
__stRecvArg.u32RtnCode = -1;
__stRecvArg.pu32IP = pu32IP;
__stRecvArg.s32DNLen = s32DNLen;
udp_recv(__pstUDPPCB, __vDNSRecv, &__stRecvArg);
//* 发送和接收
while(k<15)
{
udp_send(__pstUDPPCB, pstPbuf);
i = 0;
while(i < 30)
{
__u32RtnCode = __stRecvArg.u32RtnCode;
if(__u32RtnCode != -1)
goto __lblEnd;
OSTimeDlyHMSM(0, 0, 0, 100);
i++;
}
k++;
}
__lblEnd:
//* 收尾工作,回收占用的资源
udp_disconnect(__pstUDPPCB);
udp_remove(__pstUDPPCB);
if(__u32RtnCode != -1)
return __stRecvArg.u32RtnCode;
else
return DNS_NOT_CONN;
}
//*------------------------------------------------------------------------------------------------
//* 函数名称 : u32DNToIP
//* 功能描述 : 查询DNS服务器,将指定的域名转换为IP地址
//* 入口参数 : <pszDN>[in] 指向域名的指针
//* : <s32DNLen>[in] 域名长度
//* : <pu32IP>[in] 指向接收缓冲区(保存IP地址)的指针
//* 出口参数 : - DNS_OK : 查询成功
//* : - DNS_NOT_EXIST : 指定的域名不存在
//* : - DNS_NOT_CONN : 无法连接指定的域名服务器(主、备服务器均不可用)
//* : - DNS_OTHER : 未知错误
//*------------------------------------------------------------------------------------------------
INT32U u32DNToIP(INT8S *pszDN, INT32S s32DNLen, INT32U *pu32IP)
{
ST_PBUF *__pstPbuf = NULL;
INT32S __s32TotLen;
INT32U __u32RtnCode;
__s32TotLen = DNS_PACKET_HDR_LEN + s32DNLen + 4;
__pstPbuf = pbuf_alloc(PBUF_RAW, __s32TotLen, PBUF_POOL);
if(__pstPbuf == NULL)
return DNS_OTHER;
__ilvPacketDNSQuest(pszDN, s32DNLen, __pstPbuf);
__u32RtnCode = __u32GetIP(__pstPbuf, pu32IP, s32DNLen, DNS1_IP_ADDR);
if(__u32RtnCode == DNS_NOT_CONN || __u32RtnCode == DNS_OTHER)
__u32RtnCode = __u32GetIP(__pstPbuf, pu32IP, s32DNLen, DNS2_IP_ADDR);
pbuf_free(__pstPbuf);
return __u32RtnCode;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -