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

📄 dns.c

📁 Wiznet iRadio Source
💻 C
字号:
#include "dns.h"
#include "netconfig.h"
#include "socket.h"
#include "w5100.h"
#include "util.h"
#include <string.h>
#include <stdlib.h>

/*
********************************************************************************
Local Variable Declaration Section
********************************************************************************
*/

u8 dns_buf[MAX_BUF_SIZE];
u16   MSG_ID = 0x1122;
//extern u8 DNS_IP[4];		//	DNS server IP
extern CONFIG_MSG Config_Msg;

/*
********************************************************************************
Function Implementation Part
********************************************************************************
*/

u16 get16(u8 * s)
{
	u16 i;
	
	i = *s++ << 8;
	i = i + *s;

	return i;
}

/*
********************************************************************************
*              CONVERT A DOMAIN NAME TO THE HUMAN-READABLE FORM
*
* Description : This function converts a compressed domain name to the human-readable form
* Arguments   : msg        - is a pointer to the reply message
*               compressed - is a pointer to the domain name in reply message.
*               buf        - is a pointer to the buffer for the human-readable form name.
*               len        - is the MAX. size of buffer.
* Returns     : the length of compressed message
* Note        : 
********************************************************************************
*/
int parse_name(u8 * msg, u8 * compressed, char * buf, u16 len)
{
	u16 slen;			// Length of current segment
	u8 * cp;
	int clen = 0;		// Total length of compressed name
	int indirect = 0;	// Set if indirection encountered
	int nseg = 0;		// Total number of segments in name

	cp = compressed;

	for (;;)
	{
		slen = *cp++;	// Length of this segment

		if (!indirect) clen++;

		if ((slen & 0xc0) == 0xc0)
		{
			if(!indirect)
				clen++;
			indirect = 1;
			// Follow indirection
			cp = &msg[((slen & 0x3f)<<8) + *cp];
			slen = *cp++;
		}

		if (slen == 0)	/* zero length == all done */
			break;

		len -= slen + 1;

		if (len < 0) return -1;

		if (!indirect) clen += slen;

		while (slen-- != 0) *buf++ = (char)*cp++;
		*buf++ = '.';
		nseg++;
	}

	if (nseg == 0)
	{
		/* Root name; represent as single dot */
		*buf++ = '.';
		len--;
	}

	*buf++ = '\0';
	len--;

	return clen;	/* Length of compressed message */
}



/*
********************************************************************************
*              PARSE QUESTION SECTION
*
* Description : This function parses the qeustion record of the reply message.
* Arguments   : msg - is a pointer to the reply message
*               cp  - is a pointer to the qeustion record.
* Returns     : a pointer the to next record.
* Note        : 
********************************************************************************
*/
u8 * dns_question(u8 * msg, u8 * cp)
{
	int len;
	char   name[MAX_BUF_SIZE];

	len = parse_name(msg, cp, name, MAX_BUF_SIZE);

#ifdef	DBG_DNS	
	//myprintf("dns_question : %s\r\n", name);
#endif

	if (len == -1) return 0;

	cp += len;
	cp += 2;		/* type */
	cp += 2;		/* class */

	return cp;
}


/*
********************************************************************************
*              PARSE ANSER SECTION
*
* Description : This function parses the answer record of the reply message.
* Arguments   : msg - is a pointer to the reply message
*               cp  - is a pointer to the answer record.
* Returns     : a pointer the to next record.
* Note        : 
********************************************************************************
*/
u8 * dns_answer(u8 * msg, u8 * cp)
{
	int len, type;
	char   name[MAX_BUF_SIZE];

	len = parse_name(msg, cp, name, MAX_BUF_SIZE);

	if (len == -1) return 0;

	cp += len;
	type = get16(cp);
	cp += 2;		/* type */
	cp += 2;		/* class */
	cp += 4;		/* ttl */
	cp += 2;		/* len */

#ifdef	DBG_DNS	
	//myprintf("dns_answer : %s : %bu : %.4x\r\n", name, len, type);
#endif

	switch (type)
	{
	case TYPE_A:
		/* Just read the address directly into the structure */
		Config_Msg.Sip[0] = *cp++;
		Config_Msg.Sip[1] = *cp++;
		Config_Msg.Sip[2] = *cp++;
		Config_Msg.Sip[3] = *cp++;
		break;
	case TYPE_CNAME:
	case TYPE_MB:
	case TYPE_MG:
	case TYPE_MR:
	case TYPE_NS:
	case TYPE_PTR:
		/* These types all consist of a single domain name */
		/* convert it to ascii format */
		len = parse_name(msg, cp, name, MAX_BUF_SIZE);
		if(len == -1) return 0;

		cp += len;
		break;
	case TYPE_HINFO:
		len = *cp++;
		cp += len;

		len = *cp++;
		cp += len;
		break;
	case TYPE_MX:
		cp += 2;
		/* Get domain name of exchanger */
		len = parse_name(msg, cp, name, MAX_BUF_SIZE);
		if(len == -1) return 0;

		cp += len;
		break;
	case TYPE_SOA:
		/* Get domain name of name server */
		len = parse_name(msg, cp, name, MAX_BUF_SIZE);
		if(len == -1) return 0;

		cp += len;

		/* Get domain name of responsible person */
		len = parse_name(msg, cp, name, MAX_BUF_SIZE);
		if(len == -1) return 0;

		cp += len;

		cp += 4;
		cp += 4;
		cp += 4;
		cp += 4;
		cp += 4;
		break;
	case TYPE_TXT:
		/* Just stash */
		break;
	default:
		/* Ignore */
		break;
	}

	return cp;
}

/*
********************************************************************************
*              PARSE THE DNS REPLY
*
* Description : This function parses the reply message from DNS server.
* Arguments   : dhdr - is a pointer to the header for DNS message
*               buf  - is a pointer to the reply message.
*               len  - is the size of reply message.
* Returns     : None
* Note        : 
********************************************************************************
*/
void parseMSG(struct dhdr   * dhdr, u8 * buf)
{
	u16 tmp;
	u16 i;
	u8 * msg;
	u8 * cp;

	msg = buf;
	memset(dhdr, 0, sizeof(*dhdr));

	dhdr->id = get16(&msg[0]);
	tmp = get16(&msg[2]);
	if (tmp & 0x8000) dhdr->qr = 1;

	dhdr->opcode = (tmp >> 11) & 0xf;

	if (tmp & 0x0400) dhdr->aa = 1;
	if (tmp & 0x0200) dhdr->tc = 1;
	if (tmp & 0x0100) dhdr->rd = 1;
	if (tmp & 0x0080) dhdr->ra = 1;

	dhdr->rcode = tmp & 0xf;
	dhdr->qdcount = get16(&msg[4]);
	dhdr->ancount = get16(&msg[6]);
	dhdr->nscount = get16(&msg[8]);
	dhdr->arcount = get16(&msg[10]);

#ifdef	DBG_DNS	
	//myprintf("dhdr->qdcount : %x\r\n", (u16)dhdr->qdcount);
	//myprintf("dhdr->ancount : %x\r\n", (u16)dhdr->ancount);
	//myprintf("dhdr->nscount : %x\r\n", (u16)dhdr->nscount);
	//myprintf("dhdr->arcount : %x\r\n", (u16)dhdr->arcount);
#endif

	/* Now parse the variable length sections */
	cp = &msg[12];

	/* Question section */
	for (i = 0; i < dhdr->qdcount; i++)
	{
		cp = dns_question(msg, cp);
	}

	/* Answer section */
	for (i = 0; i < dhdr->ancount; i++)
	{
		cp = dns_answer(msg, cp);
	}

	/* Name server (authority) section */
	for (i = 0; i < dhdr->nscount; i++)
	{
		;
	}

	/* Additional section */
	for (i = 0; i < dhdr->arcount; i++)
	{
		;
	}

	MyPrintf("IP address : %d.%d.%d.%d", Config_Msg.Sip[0], Config_Msg.Sip[1], Config_Msg.Sip[2], Config_Msg.Sip[3]);
}


/*
********************************************************************************
*              PUT NETWORK BYTE ORDERED INT.
*
* Description : This function copies u16 to the network buffer with network byte order.
* Arguments   : s - is a pointer to the network buffer.
*               i - is a unsigned integer.
* Returns     : a pointer to the buffer.
* Note        : Internal Function
********************************************************************************
*/
u8 * put16(u8 * s, u16 i)
{
	*s++ = i >> 8;
	*s++ = i;

	return s;
}


/*
********************************************************************************
*              MAKE DNS QUERY MESSAGE
*
* Description : This function makes DNS query message.
* Arguments   : op   - Recursion desired
*               name - is a pointer to the domain name.
*               buf  - is a pointer to the buffer for DNS message.
*               len  - is the MAX. size of buffer.
* Returns     : the pointer to the DNS message.
* Note        : 
********************************************************************************
*/
int dns_makequery(u16 op, char * name, char   * buf, u16 len)
{
	u8 *cp;
	char *cp1;
	char   sname[MAX_BUF_SIZE];
	char *dname;
	u16 p;
	u16 dlen;

	cp = buf;

	MSG_ID++;
	cp = put16(cp, MSG_ID);
	p = (op << 11) | 0x0100;			/* Recursion desired */
	cp = put16(cp, p);
	cp = put16(cp, 1);
	cp = put16(cp, 0);
	cp = put16(cp, 0);
	cp = put16(cp, 0);

	strcpy(sname, name);
	dname = sname;
	dlen = strlen(dname);
	for (;;)
	{
		/* Look for next dot */
		cp1 = strchr(dname, '.');

		if (cp1 != NULL) len = cp1 - dname;	/* More to come */
		else len = dlen;			/* Last component */

		*cp++ = len;				/* Write length of component */
		if (len == 0) break;

		/* Copy component up to (but not including) dot */
		strncpy((char *)cp, dname, len);
		cp += len;
		if (cp1 == NULL){
			*cp++ = 0;			/* Last one; write null and finish */
			break;
		}
		dname += len+1;
		dlen -= len+1;
	}

	cp = put16(cp, 0x0001);				/* type */
	cp = put16(cp, 0x0001);				/* class */

	return ((int)((u16)(cp) - (u16)(buf)));
}

/*
********************************************************************************
*              MAKE DNS QUERY AND PARSE THE REPLY
*
* Description : This function makes DNS query message and parses the reply from DNS server.
* Arguments   : name - is a pointer to the domain name.
* Returns     : if succeeds : 1, fails : -1
* Note        : 
********************************************************************************
*/
int dns_query(u8 * name)
{
	struct dhdr  dhp;
	u8 ip[4];
	u16  len, port;
	u16  cnt;
	
	socket(SOCK_DNS, Sn_MR_UDP, 5000, 0);

	len = dns_makequery(0, name, dns_buf, MAX_BUF_SIZE);

	//MyPrintf("Querying server %d.%d.%d.%d for %s\r\n",   Config_Msg.DNS_SIP[0], Config_Msg.DNS_SIP[1], Config_Msg.DNS_SIP[2], Config_Msg.DNS_SIP[3], name);

	sendto(SOCK_DNS, dns_buf, len, Config_Msg.DNS_SIP, IPPORT_DOMAIN);
	MyPrintf("\r\nSend DNS query");

	cnt = 0;
	while (1)
	{


		if (Recv_ConfigMsg() == REMOTE_SETT) {
			break;
		}

		if ( (len = getSn_RX_RSR(SOCK_DNS)) > 0) 	
		{
			if (len > MAX_BUF_SIZE) len = MAX_BUF_SIZE;

			len = recvfrom(SOCK_DNS, dns_buf, len, ip, &port);

			close(SOCK_DNS);
			break;			
		}
		delay(5);
		if (cnt++ >= 10)
		{
			MyPrintf("timeout\r\n");
			return -1;
		}
	}
	
	parseMSG(&dhp, dns_buf);	// Convert to local format
	
	return 1;
}

⌨️ 快捷键说明

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