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

📄 dns.c

📁 analog device vdsp LAN driver and examples
💻 C
字号:
/* =============================================================================
 *
 *  Description: This is a C implementation for DNS client
 *
 * -----------------------------------------------------------------------------
 *  Comments:
 *
 * ===========================================================================*/

#include <lwip/sockets.h>
#include <lwip/inet.h>
#include "dns.h"


static int dns_id=1;
static char dns_packet[512];

#define DNS_RCV_PORT 6002
#define DNS_PORT 53
#define DNS_HOST_ADDR "10.64.53.110"

#ifdef _DEBUG_
#define DNS_ASSERT(str_,val_) do {\
	if(val_) { printf("%s\n",str_); return -1; }\
			while(0)
#else
#define DNS_ASSERT
#endif /* _DEBUG_ */

static mx_record g_mx_records[5] = {0};
/*
 * replaces each . (dot) in the host name with the dns required form.
 * each . is replaced with the number of characters followed by it.
 * including the first string, out_string must be greater than or
 * equal to the length of the host_name.
 * 
 */
int construct_dns_string(char *host_name, char *out_string)
{
int i=0,count=0;
char *src,*dst;

	src = host_name;
	dst = out_string;
	if(host_name && out_string && strlen(host_name) > 0)
	{
		for(i=0; i <= strlen(host_name); i++)
		{
			if(*src != '.')
			{
				count++;
				*++dst  = *src++;
			}
			else
			{
				*(dst - count) = count;
				src++; dst++;
				count=0;
			}
		}
		*(dst - count) = count-1;
	}
	return 1;
}
/*
 * constructs the dns query packet and returns in dns_pkt. memory is expected
 * to be allocated for the packet
 */
int dns_make_query(int id,char *dns_pkt,dns_q_type_e qtype,char *host_name)
{
char *ptr;
	ptr = dns_pkt;

	if(qtype == DNS_REQ)
	{
		*ptr++ = (char)(id >> 8); // first 2 bytes is id  0
		*ptr++ = (char)(id & 0xFF); // 1
		*ptr++ = (char)1; // flags 1 means query packet. //2
		*ptr++ = (char)0;  //3
		*ptr++ = (char)0; // 4
		*ptr++ = (char)1; // number of questions 1 //5

		*ptr++ = (char)0; // answers 0 //6
		*ptr++ = (char)0; // answers 0 //7
		
		*ptr++ = (char)0; //8
		*ptr++ = (char)0; //9

		*ptr++ = (char)0;//10
		*ptr++ = (char)0;//11

	construct_dns_string(host_name,ptr);
	ptr += strlen(host_name)+1;

	*ptr++ = 0;
	*ptr++ = 0;

	*ptr++ = 1;
	*ptr++ = 0;
	*ptr++ = 1;
	}

	return 1;
}

// returns the offset of the answers within the DNS packet.
//
int get_answer_offset(char *dns_pkt)
{
	char *ptr = dns_pkt;
	int offset=0;
	ptr +=12; // skip dns header

	// no question
	offset = *ptr & 0xFF;

	if(offset == 0)
	{
		return 0;
	}
	else
	{
		while(offset != 0 )
		{
			ptr += (offset+1);
			offset = (*ptr & 0xFF);
		}
		// type & class 2 bytes each
		ptr +=4;
	}

	return ptr - dns_pkt;
}

mx_record* dns_parse_response(char *dns_pkt, int length)
{

	int questions,answers,ans_offset,i=0,size;
	char *ptr;

	questions = ( (dns_pkt[4] & 0xFF) << 8) | (dns_pkt[5] & 0xFF);
	answers =   ( (dns_pkt[6] & 0xFF) << 8) | (dns_pkt[7] & 0xFF);

	if(!questions || !answers)
		return (mx_record*)0;

	ptr = dns_pkt;
	ans_offset = get_answer_offset(dns_pkt);

	// move ptr to point to answer list.
	ptr += ans_offset;

	// skip domain name,class,time to live,data length
	ptr += 12;

	// size of the address
	//
	size = *ptr++;

	for(i=0; i<answers; i++)
	{
	g_mx_records[i].ip_addr = (*ptr & 0xFF);
	ptr++;
	g_mx_records[i].ip_addr |= (*ptr & 0xFF) << 8 ;
	ptr++;
	g_mx_records[i].ip_addr |= (*ptr & 0xFF) << 16  ;
	ptr++;
	g_mx_records[i].ip_addr |= (*ptr & 0xFF) << 24;

	// skip domain name,class,time to live,data length
	ptr += 12;
	size = *ptr++;
	}
	return g_mx_records;
}

int dns_query_hostname(char *host_name)
{
	int sock_id,ret,i;
	struct sockaddr_in sa, ra;

	sock_id = socket(AF_INET, SOCK_DGRAM, 0);

	DNS_ASSERT("socket creation failure",sock_id < 0);

	memset(&sa, 0, sizeof(struct sockaddr_in)); // clear our address
	sa.sin_family = AF_INET;
	sa.sin_addr.s_addr = htonl(INADDR_ANY);	
	sa.sin_port = htons(DNS_RCV_PORT);  

	ret = bind(sock_id, (struct sockaddr *)&sa, sizeof(sa)); 

	DNS_ASSERT("bind failure",ret < 0);

	memset(dns_packet,0,sizeof(dns_packet));

	// Initilaize receiver's parameters
	memset((char *)&ra,0,sizeof(ra));
	ra.sin_family = AF_INET;
	ra.sin_addr.s_addr = inet_addr(DNS_HOST_ADDR);
	ra.sin_port = htons(DNS_PORT);   
	
	dns_make_query(dns_id++,dns_packet,DNS_REQ,host_name);

	ret = sendto(sock_id,dns_packet,128, 0,(struct sockaddr*)&ra,sizeof(ra));
	
	DNS_ASSERT("sendto failed",ret < 0);

	memset(dns_packet,0,sizeof(dns_packet));
	ret = recv(sock_id,dns_packet,128,0);

	DNS_ASSERT("recv failed",ret < 0);

	dns_parse_response(dns_packet,ret);

	printf("IP Address of %s is : %s\n",host_name,inet_ntoa(g_mx_records[0].ip_addr));

	return 1;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -