【无OS】基于STM32移植LWIP 1.4.1之DNS

1.前言

DNS(Domain Name System)域名系统,主要实现的功能是将域名转换成ip地址的一个服务。它是由一个分层DNS服务器实现的分布式数据库。同时,他也是一个使得主机能够查询分布式数据库的应用层协议。DNS服务器通常是一个运行BIND(Berkeley Internet Name Domain)软件的UNIX机器。DNS协议运行在UDP之上,使用53号端口。

由于有之前实现DHCP功能的基础《【无OS】基于STM32移植LWIP 1.4.1之DHCP》,所以DNS的移植很简单,下面将主要介绍LwIP DNS的流程分析。

2.LwIP如何实现DNS功能

LwIP基本上已经实现了DNS功能,我只需要打开相关的宏就可以,操作如下:

  1. lwipopts.h定义LWIP_DNS,打开DNS功能;
  2. netconf.cLwIP_Init函数中调用dns_init,来初始化DNS客户端;
  3. DHCP动态获取IP地址后,再调用DNS API dns_gethostbyname进行DNS域名解析。(参考代码如下:LwIP_DNS_Test
--- a/stm32f429_lwip_pro_list/2.stm32f429_lwip_basic_dhcp/User/LAN8742A/netconf.c
+++ b/stm32f429_lwip_pro_list/2.stm32f429_lwip_basic_dhcp/User/LAN8742A/netconf.c
@@ -31,6 +31,7 @@
 #include "lwip/tcp.h"
 #include "lwip/tcp_impl.h"
 #include "lwip/udp.h"
+#include "lwip/dns.h"
 #include "netif/etharp.h"
 #include "lwip/dhcp.h"
 #include "ethernetif.h"
@@ -137,6 +138,11 @@ void LwIP_Init(void)
   
   /* Set the link callback function, this function is called on change of link status*/
   netif_set_link_callback(&gnetif, ETH_link_callback);
+
+#if LWIP_DNS
+  dns_init();
+#endif /* LWIP_DNS */
+  
 }
 
+#ifdef LWIP_DNS
+void LwIP_DNS_Callback_handler(const char *name, struct ip_addr *ipaddr, void *arg)
+{
    
    
+	uint8_t ip[4];
+	
+	ip[0] = ipaddr->addr>>24; 
+	ip[1] = ipaddr->addr>>16;
+	ip[2] = ipaddr->addr>>8; 
+	ip[3] = ipaddr->addr; 
+
+	printf("[%s]域名解析的IP:%d.%d.%d.%d\n",name,ip[3], ip[2], ip[1], ip[0]); 
+}
+void LwIP_DNS_Test(void)
+{
    
    
+	struct ip_addr DNS_IP;
+	char hostname[] = "www.qq.com";
+
+	printf("\r\n开始DNS解析:%s\r\n", hostname);
+	dns_gethostbyname(hostname, &DNS_IP, LwIP_DNS_Callback_handler, NULL);
+}
+
+#endif
+
 #ifdef USE_DHCP
@@ -265,6 +294,10 @@ void LwIP_DHCP_Process_Handle()
 		sprintf((char*)mactxt, " %02x-%02x-%02x-%02x-%02x-%02x", gnetif.hwaddr[0], gnetif.hwaddr[1], gnetif.hwaddr[2], gnetif.hwaddr[3], gnetif.hwaddr[4], gnetif.hwaddr[5]);
 		printf("MAC addr: %s\r\n", mactxt);
 
+#ifdef LWIP_DNS
+		LwIP_DNS_Test();
+#endif
+
         LED1(ON);
       }
       else
      
--- a/stm32f429_lwip_pro_list/2.stm32f429_lwip_basic_dhcp/User/lwipopts.h
+++ b/stm32f429_lwip_pro_list/2.stm32f429_lwip_basic_dhcp/User/lwipopts.h
@@ -121,6 +121,9 @@ a lot of data that needs to be copied, this should be set high. */
    turning this on does currently not work. */
 #define LWIP_DHCP               1
 
+/* ---------- DNS options ---------- */
+#define LWIP_DNS                1
+

编译成功后,验证结果截图如下:

3.dns_init主要流程

dns_init其实主要初始化了UDP,设置的默认DNS Server地址后面会被覆盖。

4.如何获取DNS Server地址

通过前一篇文章DHCP的学习,DNS Server的地址和本机IP地址会通过DHCP Server一起下发。在dhcp.c代码 中看到dhcp_handle_ack解析DHCP Server的ACK报文时,会设置DNS Server IP地址,代码如下:

static void
dhcp_handle_ack(struct netif *netif)
{
    
    
	...
	
#if LWIP_DNS
  /* DNS servers */
  n = 0;
  while(dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n) && (n < DNS_MAX_SERVERS)) {
    
    
    ip_addr_t dns_addr;
    ip4_addr_set_u32(&dns_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n)));
    dns_setserver(n, &dns_addr);
    n++;
  }
#endif /* LWIP_DNS */

}

使用的Wireshark抓取的DHCP报文可以再次确认,如下:

在设备运行的Log中,我们也可以看到DNS Server IP地址就是DHCP ACK报文所提供的地址:(114.114.114.114, 53)

[19:33:07.252]ip_output_if: st0
[19:33:07.253]IP header:
[19:33:07.253]+-------------------------------+
[19:33:07.254]| 4 | 5 |  0x00 |        56     | (v, hl, tos, len)
[19:33:07.268]+-------------------------------+
[19:33:07.268]|        2      |000|       0   | (id, flags, offset)
[19:33:07.269]+-------------------------------+
[19:33:07.280]|  255  |   17  |    0x0000     | (ttl, proto, chksum)
[19:33:07.281]+-------------------------------+
[19:33:07.281]|  192  |  168  |    1  |  102  | (src)
[19:33:07.295]+-------------------------------+
[19:33:07.295]|  114  |  114  |  114  |  114  | (dest)
[19:33:07.296]+-------------------------------+

5. DNS域名解析流程

我们调用DNS API域名解析函数dns_gethostbyname后,解析流程大致如下:

6. DNS分析的设备Log

[19:33:07.232]开始DNS解析:www.qq.com
[19:33:07.234]dns_enqueue: "www.qq.com": use DNS entry 0
[19:33:07.248]dns_send: dns_servers[0] "www.qq.com": request
[19:33:07.249]udp_connect: connected to 0.0.0.0,port 49153
[19:33:07.250]udp_send
[19:33:07.250]udp_send: added header in given pbuf 200045ec
[19:33:07.250]udp_send: sending datagram of length 36
[19:33:07.250]udp_send: UDP packet length 36
[19:33:07.250]udp_send: UDP checksum 0x0000
[19:33:07.252]udp_send: ip_output_if (,,,,IP_PROTO_UDP,)
[19:33:07.252]ip_output_if: st0
[19:33:07.253]IP header:
[19:33:07.253]+-------------------------------+
[19:33:07.254]| 4 | 5 |  0x00 |        56     | (v, hl, tos, len)
[19:33:07.268]+-------------------------------+
[19:33:07.268]|        2      |000|       0   | (id, flags, offset)
[19:33:07.269]+-------------------------------+
[19:33:07.280]|  255  |   17  |    0x0000     | (ttl, proto, chksum)
[19:33:07.281]+-------------------------------+
[19:33:07.281]|  192  |  168  |    1  |  102  | (src)
[19:33:07.295]+-------------------------------+
[19:33:07.295]|  114  |  114  |  114  |  114  | (dest)
[19:33:07.296]+-------------------------------+
[19:33:07.297]netif->output()ip_input: iphdr->dest 0x6601a8c0 netif->ip_addr 0x6601a8c0 (0x1a8c0, 0x1a8c0, 0x66000000)
[19:33:07.309]ip_input: packet accepted on interface st
[19:33:07.310]ip_input: 
[19:33:07.310]IP header:
[19:33:07.310]+-------------------------------+
[19:33:07.323]| 4 | 5 |  0x00 |        92     | (v, hl, tos, len)
[19:33:07.323]+-------------------------------+
[19:33:07.323]|        2      |000|       0   | (id, flags, offset)
[19:33:07.339]+-------------------------------+
[19:33:07.340]|  125  |   17  |    0x969c     | (ttl, proto, chksum)
[19:33:07.340]+-------------------------------+
[19:33:07.340]|  114  |  114  |  114  |  114  | (src)
[19:33:07.342]+-------------------------------+
[19:33:07.343]|  192  |  168  |    1  |  102  | (dest)
[19:33:07.343]+-------------------------------+
[19:33:07.358]ip_input: p->len 92 p->tot_len 92
[19:33:07.358]udp_input: received datagram of length 72
[19:33:07.358]UDP header:
[19:33:07.358]+-------------------------------+
[19:33:07.372]|        53     |     49153     | (src port, dest port)
[19:33:07.372]+-------------------------------+
[19:33:07.374]|        72     |     0x65fe    | (len, chksum)
[19:33:07.374]+-------------------------------+
[19:33:07.389]udp (192.168.1.102, 49153) <-- (114.114.114.114, 53)
[19:33:07.390]pcb (0.0.0.0, 49153) --- (114.114.114.114, 53)
[19:33:07.390]udp_input: calculating checksum
[19:33:07.405]dns_recv: "www.qq.com": response = 58.250.137.36
[19:33:07.419][www.qq.com]域名解析的IP:58.250.137.36

7.资料下载地址

移植成功的完整代码下载地址如下:
https://download.csdn.net/download/ZHONGCAI0901/13033555

猜你喜欢

转载自blog.csdn.net/ZHONGCAI0901/article/details/109254481
今日推荐