欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

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

程序员文章站 2022-03-01 18:17:32
文章目录1.前言2.LwIP如何实现DNS功能3.dns_init主要流程4.如何获取DNS Server地址5. DNS域名解析流程6. DNS分析的设备Log7.资料下载地址1.前言DNS(Domain Name System)域名系统,主要实现的功能是将域名转换成ip地址的一个服务。它是由一个分层的DNS服务器实现的分布式数据库。同时,他也是一个使得主机能够查询分布式数据库的应用层协议。DNS服务器通常是一个运行BIND(Berkeley Internet Name Domain)软件的UNIX机...

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
+

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

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

3.dns_init主要流程

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

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

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报文可以再次确认,如下:

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

在设备运行的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后,解析流程大致如下:

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

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

本文地址:https://blog.csdn.net/ZHONGCAI0901/article/details/109254481