📄 dns.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 + -