概述
- 在w5500基础库中进行封装,通过域名的方式获取实际的ip地址
- 用于动态获取ntp的ip地址
DNS封装
头文件
#ifndef F1XX_TEMPLATE_W5500_DNS_H
#define F1XX_TEMPLATE_W5500_DNS_H
#include "socket.h"
#define TYPE_A 1
#define TYPE_NS 2
#define TYPE_MD 3
#define TYPE_MF 4
#define TYPE_CNAME 5
#define TYPE_SOA 6
#define TYPE_MB 7
#define TYPE_MG 8
#define TYPE_MR 9
#define TYPE_NULL 10
#define TYPE_WKS 11
#define TYPE_PTR 12
#define TYPE_HINFO 13
#define TYPE_MINFO 14
#define TYPE_MX 15
#define TYPE_TXT 16
#define TYPE_ANY 255
#define MAX_DNS_BUF_SIZE 256
struct dns_conf {
void (*delay_ms_cb)(uint32_t ms);
uint8_t dns_server_ip[4];
uint16_t dns_port;
};
void dns_config_set(struct dns_conf *cnf);
bool do_dns(SOCKET s, uint8_t *domain_name, uint8_t *dst_ip, uint32_t wait_ms);
#endif
源文件
#include "w5500_dns.h"
#define DBG_ENABLE
#define DBG_SECTION_NAME "dns"
#define DBG_LEVEL DBG_INFO
#include "sys_dbg.h"
struct dhdr {
uint16_t id;
uint8_t qr;
uint8_t opcode;
uint8_t aa;
uint8_t tc;
uint8_t rd;
uint8_t ra;
uint8_t rcode;
uint16_t qdcount;
uint16_t ancount;
uint16_t nscount;
uint16_t arcount;
};
static uint8_t DNS_BUF[MAX_DNS_BUF_SIZE] = {0};
static struct dhdr dhp = {0};
static uint16_t MSG_ID = 0x1122;
struct dns_conf *cnf_ptr = NULL;
static int dns_packet_build(uint16_t op, uint8_t *name, uint8_t *buf, uint16_t len);
static bool parse_DNS_Response(struct dhdr *pdhdr, uint8_t *pbuf, uint8_t *dst_result_ip);
static uint8_t *dns_question(uint8_t *msg, uint8_t *cp);
static uint8_t *dns_answer(uint8_t *msg, uint8_t *cp, uint8_t *dst_result_ip);
static int16_t parse_name(uint8_t *msg, uint8_t *compressed, uint16_t len);
void dns_config_set(struct dns_conf *cnf) {
cnf_ptr = cnf;
}
bool do_dns(SOCKET s, uint8_t *domain_name, uint8_t *dst_ip, uint32_t wait_ms) {
if (cnf_ptr == NULL) {
LOG_E("dns_config_set not set");
goto _exit_false;
}
if (udp_client_init(s, cnf_ptr->dns_port)) {
uint16_t len = dns_packet_build(0, domain_name, DNS_BUF, MAX_DNS_BUF_SIZE);
sendto(s, DNS_BUF, len, cnf_ptr->dns_server_ip, cnf_ptr->dns_port);
for (int i = 0; i < wait_ms / 2; ++i) {
len = w5500_socket_rx_size_read(s);
if (len > 0) break;
cnf_ptr->delay_ms_cb(2);
}
if (len > 0) {
if (len > MAX_DNS_BUF_SIZE) len = MAX_DNS_BUF_SIZE;
recvfrom_simple(s, DNS_BUF, len);
if (parse_DNS_Response(&dhp, DNS_BUF, dst_ip)) {
close(s);
return true;
} else {
LOG_W("parse_DNS_Response err");
}
} else {
LOG_D("w5500_socket_rx_size_read not rec data");
}
} else {
LOG_W("udp_client_init error");
}
_exit_false:
return false;
}
static int dns_packet_build(uint16_t op, uint8_t *name, uint8_t *buf, uint16_t len) {
uint8_t *cp = buf;
uint8_t *cp1;
uint8_t *dname;
uint16_t p;
uint16_t dlen;
MSG_ID++;
*(uint16_t *) &cp[0] = htons(MSG_ID);
p = (op << 11) | 0x0100;
*(uint16_t *) &cp[2] = htons(p);
*(uint16_t *) &cp[4] = htons(1);
*(uint16_t *) &cp[6] = htons(0);
*(uint16_t *) &cp[8] = htons(0);
*(uint16_t *) &cp[10] = htons(0);
cp += sizeof(uint16_t) * 6;
dname = name;
dlen = strlen((char *) dname);
for (;;) {
cp1 = (unsigned char *) strchr((char *) dname, '.');
if (cp1) {
len = cp1 - dname;
} else {
len = dlen;
}
*cp++ = len;
if (len == 0) break;
strncpy((char *) cp, (char *) dname, len);
cp += len;
if (!cp1) {
*cp++ = 0;
break;
}
dname += len + 1;
dlen -= len + 1;
}
*(uint16_t *) &cp[0] = htons(0x0001);
*(uint16_t *) &cp[2] = htons(0x0001);
cp += sizeof(uint16_t) * 2;
return ((int) ((uint32_t) (cp) - (uint32_t) (buf)));
}
static bool parse_DNS_Response(struct dhdr *pdhdr, uint8_t *pbuf, uint8_t *dst_result_ip) {
uint16_t tmp = 0, i = 0;
uint8_t *msg = NULL, *cp = NULL;
msg = pbuf;
memset(pdhdr, 0, sizeof(struct dhdr));
pdhdr->id = ntohs(*((uint16_t *) &msg[0]));
tmp = ntohs(*((uint16_t *) &msg[2]));
if (tmp & 0x8000)
pdhdr->qr = 1;
pdhdr->opcode = (tmp >> 11) & 0xf;
if (tmp & 0x0400)
pdhdr->aa = 1;
if (tmp & 0x0200)
pdhdr->tc = 1;
if (tmp & 0x0100)
pdhdr->rd = 1;
if (tmp & 0x0080)
pdhdr->ra = 1;
pdhdr->rcode = tmp & 0xf;
pdhdr->qdcount = ntohs(*((uint16_t *) &msg[4]));
pdhdr->ancount = ntohs(*((uint16_t *) &msg[6]));
pdhdr->nscount = ntohs(*((uint16_t *) &msg[8]));
pdhdr->arcount = ntohs(*((uint16_t *) &msg[10]));
cp = &msg[12];
for (i = 0; i < pdhdr->qdcount; i++) {
cp = dns_question(msg, cp);
}
for (i = 0; i < pdhdr->ancount; i++) {
cp = dns_answer(msg, cp, dst_result_ip);
}
for (i = 0; i < pdhdr->nscount; i++) { ;
}
for (i = 0; i < pdhdr->arcount; i++) { ;
}
if (pdhdr->rcode == 0)
return 1;
else
return 0;
}
uint8_t *dns_question(uint8_t *msg, uint8_t *cp) {
int16_t len = parse_name(msg, cp, MAX_DNS_BUF_SIZE);
if (len == -1)return 0;
cp += len;
cp += 2;
cp += 2;
return cp;
}
static uint8_t *dns_answer(uint8_t *msg, uint8_t *cp, uint8_t *dst_result_ip) {
int16_t len, type;
len = parse_name(msg, cp, MAX_DNS_BUF_SIZE);
if (len == -1)
return 0;
cp += len;
type = ntohs(*((uint16_t *) &cp[0]));
cp += 2;
cp += 2;
cp += 4;
cp += 2;
switch (type) {
case TYPE_A:
dst_result_ip[0] = *cp++;
dst_result_ip[1] = *cp++;
dst_result_ip[2] = *cp++;
dst_result_ip[3] = *cp++;
break;
case TYPE_CNAME:
case TYPE_MB:
case TYPE_MG:
case TYPE_MR:
case TYPE_NS:
case TYPE_PTR:
len = parse_name(msg, cp, MAX_DNS_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;
len = parse_name(msg, cp, MAX_DNS_BUF_SIZE);
if (len == -1)
return 0;
cp += len;
break;
case TYPE_SOA:
len = parse_name(msg, cp, MAX_DNS_BUF_SIZE);
if (len == -1)
return 0;
cp += len;
len = parse_name(msg, cp, MAX_DNS_BUF_SIZE);
if (len == -1)
return 0;
cp += len;
cp += 4;
cp += 4;
cp += 4;
cp += 4;
cp += 4;
break;
case TYPE_TXT:
break;
default:
break;
}
return cp;
}
static int16_t parse_name(uint8_t *msg, uint8_t *compressed, uint16_t len) {
static int8_t name[MAX_DNS_BUF_SIZE];
uint16_t slen = 0;
uint8_t *cp = NULL;
int16_t clen = 0;
int16_t indirect = 0;
int16_t nseg = 0;
int8_t *buf = NULL;
buf = name;
cp = compressed;
for (;;) {
slen = *cp++;
if (!indirect)
clen++;
if ((slen & 0xc0) == 0xc0) {
if (!indirect)
clen++;
indirect = 1;
cp = &msg[((slen & 0x3f) << 8) + *cp];
slen = *cp++;
}
if (slen == 0)
break;
len -= slen + 1;
if (len <= 0)
return -1;
if (!indirect)
clen += slen;
while (slen-- != 0)
*buf++ = (int8_t) *cp++;
*buf++ = '.';
nseg++;
}
if (nseg == 0)
{
*buf++ = '.';
len--;
}
*buf++ = '\0';
len--;
return clen;
}
测试
配置文件
#include "app_conf.h"
#include "w5500_config.h"
#if APP_CONFIG_W5500
#define DBG_ENABLE
#define DBG_SECTION_NAME "w5500"
#define DBG_LEVEL W5500_DBG_LEVEL
#include "sys_dbg.h"
#include "w5500_dns.h"
#include "w5500_ntp.h"
#define W5500_CS stm_port_define(B,12)
#define W5500_RST stm_port_define(C,7)
extern struct net_date_time gb_app_time;
static SPI_HandleTypeDef *w5500_spi = NULL;
static void send_and_rec_bytes(uint8_t *in_dat, uint8_t *out_data, uint16_t len) {
while (HAL_SPI_GetState(w5500_spi) != HAL_SPI_STATE_READY);
HAL_SPI_TransmitReceive(w5500_spi, in_dat, out_data, len, 1000);
while (HAL_SPI_GetState(w5500_spi) != HAL_SPI_STATE_READY);
}
static void send_only(uint8_t *in_data, uint16_t len) {
HAL_SPI_Transmit(w5500_spi, in_data, len, 1000);
}
static void W5500_RST_HIGH(void) { stm_pin_high(W5500_RST); }
static void W5500_RST_LOW(void) { stm_pin_low(W5500_RST); }
static void W5500_CS_LOW(void) { stm_pin_low(W5500_CS); }
static void W5500_CS_HIGH(void) { stm_pin_high(W5500_CS); }
static void W5500_Driver_MspInit(void) {
stm32_pin_mode(W5500_CS, pin_mode_output);
stm32_pin_mode(W5500_RST, pin_mode_output);
stm_pin_low(W5500_RST);
stm_pin_low(W5500_CS);
bsp_SpiHandleInit(w5500_spi, SPI_BAUDRATEPRESCALER_2, spi_mode_3);
}
module_w5500_t w5500_conf = {
.base_conf={
.socket_num = 4,
.rx_size={4, 4, 4, 4},
.tx_size={4, 4, 4, 4},
},
.net_conf={
.ip={192, 168, 199, 12},
.gw={192, 168, 199, 1},
.sub={255, 255, 255, 0},
},
.driver={
.cs_high = W5500_CS_HIGH,
.cs_low = W5500_CS_LOW,
.rst_high= W5500_RST_HIGH,
.rst_low=W5500_RST_LOW,
.delay = HAL_Delay,
.send_and_rec_bytes = send_and_rec_bytes,
.send_only =send_only
},
.api = {
.msp_init=W5500_Driver_MspInit,
}
};
uint8_t ntp_domain[] = {"ntp.ntsc.ac.cn"};
static struct dns_conf net_dns_cnf = {
.dns_server_ip={114, 114, 114, 114},
.dns_port = 53,
.delay_ms_cb = HAL_Delay
};
static struct ntp_conf net_ntp_conf = {
.ntp_port = 123,
.delay_ms_cb = HAL_Delay
};
static void w5500_pre_init(void) {
w5500_spi = conv_spi_handle_ptr(handle_get_by_id(spi2_id));
module_w5500_init(&w5500_conf);
uint32_t uid0 = HAL_GetUIDw0();
uint32_t uid1 = HAL_GetUIDw1();
uint32_t uid2 = HAL_GetUIDw2();
uint8_t mac[6] = {0, uid0 >> 8, uid1, uid1 >> 8, uid2, uid2 >> 8};
memcpy(w5500_conf.net_conf.mac, mac, sizeof(mac));
}
static void w5500_init(void) {
w5500_conf.api.msp_init();
w5500_conf.net_conf_init();
uint8_t ip[4];
w5500_reg_ip_read(ip);
LOG_D("w5500_reg_ip_read:%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
w5500_reg_gw_read(ip);
LOG_D("w5500_reg_gw_read:%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
}
static void w5500_after_init(void) {
uint8_t try_cnt = 3;
SOCKET sn = 1;
#if APP_CONFIG_W5500_DNS
for (int i = 0; i < try_cnt; ++i) {
dns_config_set(&net_dns_cnf);
if (do_dns(sn, ntp_domain, net_ntp_conf.ntp_server, 500)) {
LOG_D("dns parse result ip:%d.%d.%d.%d",
net_ntp_conf.ntp_server[0], net_ntp_conf.ntp_server[1],
net_ntp_conf.ntp_server[2], net_ntp_conf.ntp_server[3]
);
goto next_step;
}
}
LOG_D("do dns try cnt over");
return;
next_step:
#endif
#if APP_CONFIG_W5500_NTP
ntp_config_set(&net_ntp_conf);
for (int i = 0; i < try_cnt; ++i) {
if (ntp_date_time_get(sn, 500, &gb_app_time)) {
HAL_TIM_Base_Start_IT(handle_get_by_id(tim6_id));
goto exit_ok;
}
}
LOG_W("ntp_date_time_get time out");
return;
exit_ok:
LOG_D("NTP TIME:%d-%02d-%02d %02d:%02d:%02d",
gb_app_time.year, gb_app_time.month, gb_app_time.day,
gb_app_time.hour, gb_app_time.min, gb_app_time.sec
);
#else
return;
#endif
}
app_init_export(w5500_net_conf, w5500_pre_init, w5500_init, w5500_after_init);
#endif
结果