序号 | 内容 |
---|---|
1 | 《教你动手写UDP协议栈-UDP协议栈格式》 |
2 | 《教你动手写UDP协议栈-DHCP报文解析》 |
3 | 《教你动手写UDP协议栈-OTA上位机》 |
4 | 《教你动手写UDP协议栈-DNS报文解析》 |
工具 | 介绍 |
---|---|
WireShark | 网络封包分析软件,分析数据包 |
CMD | window 命令行 |
字段 | 说明 |
---|---|
Transaction ID | 辨别DNS应答报文是哪个请求报文的响应 |
QR | Flags字段,1为响应,0位查询 |
OpCode | Flags字段,查询或响应类型,0为标准,1为反向,2为服务器状态请求 |
AA | Flags字段,授权回答 |
TC | Flags字段,截断,1表示超过512字节并已被截断,0表示没有发送截断 |
RD | Flags字段,是否希望得到递归回答 |
RA | Flags字段,响应报文中为1便是得到递归响应 |
Z | Flags字段,0 |
AD | Flags字段,真是数据 |
CD | Flags字段,禁止校验 |
RCODE | Flags字段,返回码:0-无差错,1-格式错误,2-服务器失效,3-不存在域名,4-查询类型不支持,5-被禁止,6-15保留 |
Questions | Flags字段,查询数 |
Answer | Flags字段,资源记录数 |
Authority | Flags字段,授权资源记录数 |
Additional | Flags字段,额外资源记录数 |
/** DNS message header */
PACK_STRUCT_BEGIN
struct dns_header {
PACK_STRUCT_FIELD(uint16_t id);
PACK_STRUCT_FIELD(uint8_t flags1);
PACK_STRUCT_FIELD(uint8_t flags2);
PACK_STRUCT_FIELD(uint16_t numquestions);
PACK_STRUCT_FIELD(uint16_t numanswers);
PACK_STRUCT_FIELD(uint16_t numauthrr);
PACK_STRUCT_FIELD(uint16_t numextrarr);
}PACK_STRUCT_STRUCT;
PACK_STRUCT_END
字段 | 说明 |
---|---|
name | 查询名称,不定长 |
type | 查询类型 |
class | 查询类 |
PACK_STRUCT_BEGIN
struct dns_query {
PACK_STRUCT_FIELD(uint16_t type);
PACK_STRUCT_FIELD(uint16_t class);
}PACK_STRUCT_STRUCT;
PACK_STRUCT_END
字段 | 说明 |
---|---|
name | 查询名称,不定长 |
type | 查询类型 |
class | 查询类 |
TTL | 该资源记录的生命周期 |
data length | 资源数据长度 |
address | 返回的IP地址,即域名转换的IP地址 |
struct dns_answer {
PACK_STRUCT_FIELD(uint16_t name);
PACK_STRUCT_FIELD(uint16_t type);
PACK_STRUCT_FIELD(uint16_t class);
PACK_STRUCT_FIELD(uint32_t ttl);
PACK_STRUCT_FIELD(uint16_t len);
PACK_STRUCT_FIELD(struct ip_addr server_ip);
}PACK_STRUCT_STRUCT;
PACK_STRUCT_END
static void dns_packet_output(uint8_t *host_name)
{
struct dns_header dns_hdr = {0};
struct dns_query dns_qry = {0};
struct dest_device_info dest_info = {0};
uint8_t *dns_packet = NULL;
uint8_t *dns_name = NULL;
uint16_t query_index = 0;
uint16_t label_len = 0;
uint16_t dns_name_len = strlen(host_name) + 2;
dns_packet = malloc(DNS_HDR_SIZE + dns_name_len + DNS_QUERY_SIZE);
dns_name = malloc(strlen(host_name) + 2);
if(dns_packet != NULL && dns_name !=NULL)
{
//打包DNS header
memset(&dns_hdr, 0, DNS_HDR_SIZE);
dns_hdr.id = mu_htons(TRANSACTION_ID);
dns_hdr.flags1 = DNS_FLAG1_RD;
dns_hdr.numquestions = mu_htons(1);
memcpy(dns_packet, &dns_hdr, DNS_HDR_SIZE);
//将域名转换DNS数据包格式
change_to_dns_name(dns_name, host_name);
memcpy(dns_packet + DNS_HDR_SIZE, dns_name, dns_name_len);
dns_qry.type = mu_htons(DNS_RRTYPE_A);
dns_qry.class = mu_htons(DNS_RRCLASS_IN);
//打包DNS query
memcpy(dns_packet + DNS_HDR_SIZE + dns_name_len, &dns_qry, DNS_QUERY_SIZE);
memcpy(&dest_info.dest_mac, get_gw_mac(), MAC_ADDR_SIZE);
memcpy(&dest_info.dest_ip, get_dns_server(), IP_ADDR_SIZE);
dest_info.src_port = DNS_CLIENT_PORT;
dest_info.dest_port = DNS_SERVER_PORT;
//通过UDP报文发送
mini_udp_output(&dest_info, dns_packet, (DNS_HDR_SIZE + dns_name_len + DNS_QUERY_SIZE));
}
if(dns_packet != NULL)
{
free(dns_packet);
}
if(dns_name != NULL)
{
free(dns_name);
}
}
static void dns_packet_input(void *dns_packet_data)
{
struct dns_header *dns_hdr = {0};
struct dns_answer *dns_ans = {0};
uint16_t dns_name_len = strlen("www.csdn.net") + 2;
uint8_t *server_dns_name = malloc(strlen("www.csdn.net") + 2);
if(server_dns_name == NULL)
{
LOG_E("malloc fail!!\n");
return;
}
dns_hdr = dns_packet_data;
if(dns_hdr->id == mu_ntohs(TRANSACTION_ID)
&& (dns_hdr->numanswers > 1))
{
change_to_dns_name(server_dns_name, "www.csdn.net");
if(strncmp(dns_packet_data + DNS_HDR_SIZE, server_dns_name, dns_name_len) == 0)
{
dns_ans = dns_packet_data + DNS_HDR_SIZE + dns_name_len + DNS_QUERY_SIZE;
printf("CSDN IP: %d:%d:%d:%d \n", dns_ans->server_ip.addr[0],
dns_ans->server_ip.addr[1],
dns_ans->server_ip.addr[2],
dns_ans->server_ip.addr[3]);
}
}
free(server_dns_name);
}
本文分享自 Rice 嵌入式开发技术分享 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!