1
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdint.h>
5 #include <unistd.h>
6 #include <sys/socket.h>
7
8 #include "linkkit/wrappers/wrappers.h"
9 #include "dns.h"
10
11 /* dns header field */
12 #define DNS_ID_FIELD (0x6666)
13 #define DNS_CTRL_FIELD (0x0100)
14 #define DNS_QUESTION_COUNT_FIELD (0x0001)
15 #define DNS_ANSWER_COUNT_FIELD (0x0000)
16 #define DNS_AUTHORITY_COUNT_FIELD (0x0000)
17 #define DNS_ADDITIONAL_COUNT_FIELD (0x0000)
18
19 /* dns record section */
20 #define DNS_QTYPE_FIELD (0x0001)
21 #define DNS_QCLASS_FIELD (0x0001)
22
23 /* dns server and resolve result */
24 #define DNS_SERVER_COUNT (3)
25
26 static char g_dns_ip_list[DNS_RESULT_COUNT][16];
27
28 static char *g_dns_server_list[DNS_SERVER_COUNT] = { "223.5.5.5", "223.6.6.6",
29 "8.8.8.8" };
30
dns_domain_check(char * domain)31 static int dns_domain_check(char *domain)
32 {
33 uint32_t idx = 0;
34
35 for (idx = 0; idx < strlen(domain); idx++) {
36 if (domain[idx] == '.') {
37 continue;
38 }
39 if (domain[idx] < 0x30 || domain[idx] > 0x39) {
40 return 0;
41 }
42 }
43
44 return -1;
45 }
46
dns_uint2str(uint8_t * input,char * output)47 static void dns_uint2str(uint8_t *input, char *output)
48 {
49 uint8_t idx = 0, i = 0, j = 0;
50 uint8_t pos = 0;
51 char temp[10] = { 0 };
52
53 memset(output, 0, 16);
54 for (idx = 0; idx < 4; idx++) {
55 i = 0;
56 j = 0;
57 pos = input[idx];
58 memset(temp, 0, 10);
59 do {
60 temp[i++] = pos % 10 + '0';
61 } while ((pos /= 10) > 0);
62
63 do {
64 output[--i + strlen(output)] = temp[j++];
65 } while (i > 0);
66 if (idx < 3)
67 output[strlen(output)] = '.';
68 }
69 }
70
dns_request_message(char * domain,uint8_t buffer[1024],uint32_t * index)71 void dns_request_message(char *domain, uint8_t buffer[1024], uint32_t *index)
72 {
73 uint32_t idx = 0;
74
75 /* identification */
76 buffer[idx++] = (DNS_ID_FIELD >> 8) & 0x00FF;
77 buffer[idx++] = (DNS_ID_FIELD) & 0x00FF;
78
79 /* control */
80 buffer[idx++] = (DNS_CTRL_FIELD >> 8) & 0x00FF;
81 buffer[idx++] = (DNS_CTRL_FIELD) & 0x00FF;
82
83 /* question count */
84 buffer[idx++] = (DNS_QUESTION_COUNT_FIELD >> 8) & 0x00FF;
85 buffer[idx++] = (DNS_QUESTION_COUNT_FIELD) & 0x00FF;
86
87 /* answer count */
88 buffer[idx++] = (DNS_ANSWER_COUNT_FIELD >> 8) & 0x00FF;
89 buffer[idx++] = (DNS_ANSWER_COUNT_FIELD) & 0x00FF;
90
91 /* authority count */
92 buffer[idx++] = (DNS_AUTHORITY_COUNT_FIELD >> 8) & 0x00FF;
93 buffer[idx++] = (DNS_AUTHORITY_COUNT_FIELD) & 0x00FF;
94
95 /* additional count */
96 buffer[idx++] = (DNS_ADDITIONAL_COUNT_FIELD >> 8) & 0x00FF;
97 buffer[idx++] = (DNS_ADDITIONAL_COUNT_FIELD) & 0x00FF;
98
99 /* qname */
100 {
101 uint32_t section_start = 0, qname_idx = 0;
102 do {
103 if (domain[qname_idx] == '.' || qname_idx == strlen(domain)) {
104 buffer[idx++] = (uint32_t)(qname_idx - section_start);
105 memcpy(&buffer[idx], &domain[section_start],
106 (qname_idx - section_start));
107 idx += (qname_idx - section_start);
108 section_start = qname_idx + 1;
109 }
110
111 if (qname_idx == strlen(domain)) {
112 break;
113 }
114
115 qname_idx++;
116 } while (1);
117 buffer[idx++] = 0x00;
118 }
119
120 /* qtype */
121 buffer[idx++] = (DNS_QTYPE_FIELD >> 8) & 0x00FF;
122 buffer[idx++] = (DNS_QTYPE_FIELD) & 0x00FF;
123
124 /* qclass */
125 buffer[idx++] = (DNS_QCLASS_FIELD >> 8) & 0x00FF;
126 buffer[idx++] = (DNS_QCLASS_FIELD) & 0x00FF;
127
128 *index = idx;
129 }
130
dns_response_message(uint8_t buffer[1024],uint32_t buffer_len,char * ip[DNS_RESULT_COUNT])131 int dns_response_message(uint8_t buffer[1024], uint32_t buffer_len,
132 char *ip[DNS_RESULT_COUNT])
133 {
134 int res = 0;
135 uint32_t idx = 0, rd_len = 0, dns_count = 0;
136
137 /* skip dns header */
138 idx += 12;
139
140 /* skip question qname section */
141 while (buffer[idx] != 0x00) {
142 idx += buffer[idx] + 1;
143 }
144
145 if (idx >= buffer_len) {
146 return -1;
147 }
148
149 /* skip 0x00, question qtype and qclass section */
150 idx += 1 + 4;
151
152 memset(g_dns_ip_list, 0, DNS_RESULT_COUNT * 16);
153
154 while (idx < buffer_len) {
155 /* name, type, class and TTL */
156 idx += 2 + 2 + 2 + 4;
157
158 rd_len = (buffer[idx++] << 8);
159 rd_len |= buffer[idx++];
160
161 if (idx >= buffer_len) {
162 return -1;
163 }
164
165 if (rd_len == 4) {
166 if (dns_count < DNS_RESULT_COUNT) {
167 dns_uint2str(&buffer[idx], g_dns_ip_list[dns_count]);
168 ip[dns_count] = g_dns_ip_list[dns_count];
169 dns_count++;
170 } else {
171 break;
172 }
173 }
174
175 idx += rd_len;
176 }
177
178 if (dns_count == 0) {
179 return -1;
180 }
181
182 return 0;
183 }
184
dns_resolve(char dns[16],char * domain,char * ip[DNS_RESULT_COUNT])185 int dns_resolve(char dns[16], char *domain, char *ip[DNS_RESULT_COUNT])
186 {
187 int res = 0, sock_fd = 0;
188 struct sockaddr_in dest;
189 uint32_t dest_len = 0;
190 uint8_t send_message[1024] = { 0 }, recv_message[1024] = { 0 };
191 uint32_t idx = 0;
192 fd_set send_recv_sets;
193 struct timeval timeselect;
194
195 res = dns_domain_check(domain);
196 if (res < 0) {
197 if (strlen(domain) >= 16) {
198 return -1;
199 }
200 memset(g_dns_ip_list, 0, DNS_RESULT_COUNT * 16);
201 memcpy(g_dns_ip_list[0], domain, strlen(domain));
202 ip[0] = g_dns_ip_list[0];
203 return 0;
204 }
205
206 sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
207 if (sock_fd < 0) {
208 HAL_Printf("dns socket: \r\n");
209 return -1;
210 }
211
212 dest.sin_family = AF_INET;
213 dest.sin_port = htons(53);
214 dest.sin_addr.s_addr = inet_addr(dns);
215
216 /* set select timeout */
217 timeselect.tv_sec = 3;
218 timeselect.tv_usec = 0;
219
220 /* dns request message */
221 dns_request_message(domain, send_message, &idx);
222
223 /* send to dns server */
224 FD_ZERO(&send_recv_sets);
225 FD_SET(sock_fd, &send_recv_sets);
226 res = select(sock_fd + 1, NULL, &send_recv_sets, NULL, ×elect);
227 if (res <= 0) {
228 close(sock_fd);
229 return -1;
230 }
231 if (FD_ISSET(sock_fd, &send_recv_sets)) {
232 res = sendto(sock_fd, (void *)send_message, (size_t)idx, 0,
233 (struct sockaddr *)&dest, sizeof(dest));
234 if (res < 0) {
235 HAL_Printf("send dns request message failed.\r\n");
236 close(sock_fd);
237 return -1;
238 }
239
240 if (res != idx) {
241 close(sock_fd);
242 return -1;
243 }
244 }
245
246 /* recv from dns server */
247 FD_ZERO(&send_recv_sets);
248 FD_SET(sock_fd, &send_recv_sets);
249 res = select(sock_fd + 1, &send_recv_sets, NULL, NULL, ×elect);
250 if (res <= 0) {
251 close(sock_fd);
252 return -1;
253 }
254 if (FD_ISSET(sock_fd, &send_recv_sets)) {
255 dest_len = sizeof(dest);
256 if ((res = recvfrom(sock_fd, (void *)recv_message, 1024, 0,
257 (struct sockaddr *)&dest, &dest_len)) < 0) {
258 HAL_Printf("send dns request message failed;\r\n");
259 close(sock_fd);
260 return -1;
261 }
262 }
263
264 close(sock_fd);
265
266 return dns_response_message(recv_message, res, ip);
267 }
268
dns_getaddrinfo(char * domain,char * ip[DNS_RESULT_COUNT])269 int dns_getaddrinfo(char *domain, char *ip[DNS_RESULT_COUNT])
270 {
271 int res = 0;
272 uint8_t idx = 0;
273
274 memset(g_dns_ip_list, 0, DNS_RESULT_COUNT * 16);
275 for (idx = 0; idx < DNS_SERVER_COUNT; idx++) {
276 HAL_Printf("[prt] dns server: %s\n", g_dns_server_list[idx]);
277 res = dns_resolve(g_dns_server_list[idx], domain, ip);
278 if (res < 0) {
279 continue;
280 }
281 return 0;
282 }
283 return -1;
284 }
285