📄 dns_client.c
字号:
//*------------------------------------------------------------------------------------------------
//* 文件名 : dns_clinet.c
//* 功能描述 : dns客户端
//* 作者 : 焦海波
//* 版本 : 0.1
//* 建立日期、时间 : 2006/08/10 15:23
//* 最近修改日期、时间 :
//* 修改原因 :
//*------------------------------------------------------------------------------------------------
//*------------------------------------------ 头文件 -----------------------------------------------
#include "/uCOS_II/includes.h"
#include "/LwIP/include/lwip/tcpip.h"
#include "dns_client.h"
//*================================================================================================
//* 函 数 区
//*================================================================================================
//*------------------------------------------------------------------------------------------------
//* 函数名称 : ulDNToIP
//* 功能描述 : 查询DNS服务器,将指定的域名转换为IP地址
//* : <pszDN>[in] 指向域名的指针
//* : <lDNLen>[in] 域名长度
//* : <pstPbuf>[in] 指向st_pbuf结构的指针,它这个结构保存要发送的DNS的查询包
//* 出口参数 : 无
//*------------------------------------------------------------------------------------------------
__inline void __ilvPacketDNSQuest(BYTE *pszDN, LONG lDNLen, st_pbuf *pstPbuf)
{
ST_DNS_PACKET_HDR *__pstDNSPacket;
BST_ID_AND_FLAGS *__pbstIDAndFlags;
__pstDNSPacket = (ST_DNS_PACKET_HDR*)pstPbuf->payload;
__pstDNSPacket->ulIDAndFlags = 0x00000000;
__pbstIDAndFlags = &__pstDNSPacket->ulIDAndFlags;
__pbstIDAndFlags->bitID = 0x0608;
__pbstIDAndFlags->bitIsRD = 0x1;
__pstDNSPacket->uwQCount = 0x0100;
__pstDNSPacket->uwACount = 0x0000;
__pstDNSPacket->uwAuthCount = 0x0000;
__pstDNSPacket->uwARC = 0x0000;
memcpy((UBYTE*)pstPbuf->payload + DNS_PACKET_HDR_LEN, pszDN, lDNLen);
*((UBYTE*)pstPbuf->payload + DNS_PACKET_HDR_LEN + lDNLen) = 0x00;
*((UBYTE*)pstPbuf->payload + DNS_PACKET_HDR_LEN + lDNLen + 1) = DNS_PACKET_QUERY_TYPE;
*((UBYTE*)pstPbuf->payload + DNS_PACKET_HDR_LEN + lDNLen + 2) = 0x00;
*((UBYTE*)pstPbuf->payload + DNS_PACKET_HDR_LEN + lDNLen + 3) = DNS_PACKET_QUERY_CLASS;
}
//*------------------------------------------------------------------------------------------------
//* 函数名称 : __ilulParseRespDNSPacket
//* 功能描述 : 解析DNS服务器响应的数据包
//* 入口参数 : <pstPbuf>[in] 指向ST_NETBUF的指针
//* : <pulIP>[in] 指向接收缓冲区(保存IP地址)的指针
//* : <lDNlen>[in] 要查询域名的长度
//* 出口参数 : - DNS_OK : 查询成功
//* : - DNS_NOT_EXIST : 指定的域名不存在
//* : - DNS_OTHER : 未知错误
//*------------------------------------------------------------------------------------------------
__inline ULONG __ilulParseRespDNSPacket(st_pbuf *pstPbuf, ULONG *pulIP, LONG lDNLen)
{
ST_DNS_PACKET_HDR *__pstDNSPacket;
ULONG __ulVal;
BST_ID_AND_FLAGS *__pbstIDAndFlags;
void *__pvData;
UWORD __uwACount, __uwAnswerDataLen, __uwOffset;
__pstDNSPacket = (ST_DNS_PACKET_HDR *)pstPbuf->payload;
__ulVal = __pstDNSPacket->ulIDAndFlags;
__pbstIDAndFlags = &__ulVal;
if(__pbstIDAndFlags->bitOptResult == 0)
{
__uwACount = macHighToLowForWord(__pstDNSPacket->uwACount);
__uwOffset = lDNLen + 14;
while(__uwACount > 0)
{
__pvData = (UBYTE*)pstPbuf->payload + DNS_PACKET_HDR_LEN + __uwOffset;
__uwAnswerDataLen = macHighToLowForWord(*((__packed UWORD*)__pvData));
if((__uwAnswerDataLen == 4) && macHighToLowForWord(*((__packed UWORD*)((UBYTE*)__pvData - 8))) == DNS_PACKET_QUERY_TYPE)
{
*pulIP = *((__packed ULONG *)((UBYTE*)__pvData + 2));
return DNS_OK;
}
__uwOffset += 12 + __uwAnswerDataLen;
__uwACount--;
}
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地址
//* : <uwPort>[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, UWORD uwPort)
{
if(pstPbuf != NULL)
{
pstArg->ulRtnCode = __ilulParseRespDNSPacket(pstPbuf, pstArg->pulIP, pstArg->lDNLen);
pbuf_free(pstPbuf);
}
}
//*------------------------------------------------------------------------------------------------
//* 函数名称 : __ulGetIP
//* 功能描述 : 查询DNS服务器,获取指定域名绑定的IP地址,这里只能使用协议栈直接接口实现,使用其提供
//* : 的API无法满足需求。如果接收DNS响应包使用netconn_recv函数非常容易阻塞系统,因为UDP
//* : 不可靠。
//* : <pstPbuf>[in] 指向st_pbuf结构的指针,它这个结构保存要发送的DNS的查询包
//* : <pulIP>[in] 指向接收缓冲区(保存IP地址)的指针
//* : <lDNLen>[in] 要查询的域名长度
//* : <ulDNSIP>[in] DNS服务器的IP地址
//* 出口参数 : - DNS_OK : 查询成功
//* : - DNS_NOT_EXIST : 指定的域名不存在
//* : - DNS_NOT_CONN : 无法连接指定的域名服务器(主、备服务器均不可用)
//* : - DNS_OTHER : 未知错误
//*------------------------------------------------------------------------------------------------
ULONG __ulGetIP(st_pbuf *pstPbuf, ULONG *pulIP, LONG lDNLen, ULONG ulDNSIP)
{
st_ip_addr __stIPAddr;
ST_UDP_PCB *__pstUDPPCB;
ST_RECV_FUN_ARG __stRecvArg;
LONG i, k = 0;
ULONG __ulRtnCode;
__pstUDPPCB = udp_new();
if(__pstUDPPCB == NULL)
return DNS_OTHER;
__stIPAddr.addr = htonl(ulDNSIP);
if(udp_connect(__pstUDPPCB, &__stIPAddr, DNS_PORT) != ERR_OK)
return DNS_OTHER;
memset(&__stRecvArg, 0, sizeof(ST_RECV_FUN_ARG));
__stRecvArg.ulRtnCode = -1;
__stRecvArg.pulIP = pulIP;
__stRecvArg.lDNLen = lDNLen;
udp_recv(__pstUDPPCB, __vDNSRecv, &__stRecvArg);
//* 发送和接收
while(k<15)
{
udp_send(__pstUDPPCB, pstPbuf);
i = 0;
while(i < 30)
{
__ulRtnCode = __stRecvArg.ulRtnCode;
if(__ulRtnCode != -1)
goto __lbEnd;
OSTimeDlyHMSM(0, 0, 0, 100);
i++;
}
k++;
}
__lbEnd:
//* 收尾工作,回收占用的资源
udp_disconnect(__pstUDPPCB);
udp_remove(__pstUDPPCB);
if(__ulRtnCode != -1)
return __stRecvArg.ulRtnCode;
else
return DNS_NOT_CONN;
}
//*------------------------------------------------------------------------------------------------
//* 函数名称 : ulDNToIP
//* 功能描述 : 查询DNS服务器,将指定的域名转换为IP地址
//* 入口参数 : <pszDN>[in] 指向域名的指针
//* : <lDNLen>[in] 域名长度
//* : <pulIP>[in] 指向接收缓冲区(保存IP地址)的指针
//* 出口参数 : - DNS_OK : 查询成功
//* : - DNS_NOT_EXIST : 指定的域名不存在
//* : - DNS_NOT_CONN : 无法连接指定的域名服务器(主、备服务器均不可用)
//* : - DNS_OTHER : 未知错误
//*------------------------------------------------------------------------------------------------
ULONG ulDNToIP(BYTE *pszDN, LONG lDNLen, ULONG *pulIP)
{
st_pbuf *__pstPbuf = NULL;
LONG __lTotLen;
ULONG __ulRtnCode;
__lTotLen = DNS_PACKET_HDR_LEN + lDNLen + 4;
__pstPbuf = pbuf_alloc(PBUF_RAW, __lTotLen, PBUF_POOL);
if(__pstPbuf == NULL)
return DNS_OTHER;
__ilvPacketDNSQuest(pszDN, lDNLen, __pstPbuf);
__ulRtnCode = __ulGetIP(__pstPbuf, pulIP, lDNLen, DNS1_IP_ADDR);
if(__ulRtnCode == DNS_NOT_CONN)
__ulRtnCode = __ulGetIP(__pstPbuf, pulIP, lDNLen, DNS2_IP_ADDR);
pbuf_free(__pstPbuf);
return __ulRtnCode;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -