⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dns_client.c

📁 基于AT91SAM7x256的硬件平台的WEB服务器源码(A&shy DS版本, ucOS_II+LWIP+自己编写的DNS查询工具)
💻 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 + -