WIZlib Library API  ver 1.0
WIZlib Library API User Menual
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dns.c
Go to the documentation of this file.
1 
12 //#define FILE_LOG_SILENCE
13 #include "protocol/DNS/dns.h"
14 
15 
16 #define INITRTT 2000L /* Initial smoothed response time */
17 #define MAXCNAME 10 /* Maximum amount of cname recursion */
18 
19 #define TYPE_A 1 /* Host address */
20 #define TYPE_NS 2 /* Name server */
21 #define TYPE_MD 3 /* Mail destination (obsolete) */
22 #define TYPE_MF 4 /* Mail forwarder (obsolete) */
23 #define TYPE_CNAME 5 /* Canonical name */
24 #define TYPE_SOA 6 /* Start of Authority */
25 #define TYPE_MB 7 /* Mailbox name (experimental) */
26 #define TYPE_MG 8 /* Mail group member (experimental) */
27 #define TYPE_MR 9 /* Mail rename name (experimental) */
28 #define TYPE_NULL 10 /* Null (experimental) */
29 #define TYPE_WKS 11 /* Well-known sockets */
30 #define TYPE_PTR 12 /* Pointer record */
31 #define TYPE_HINFO 13 /* Host information */
32 #define TYPE_MINFO 14 /* Mailbox information (experimental)*/
33 #define TYPE_MX 15 /* Mail exchanger */
34 #define TYPE_TXT 16 /* Text strings */
35 #define TYPE_ANY 255 /* Matches any type */
36 
37 #define CLASS_IN 1 /* The ARPA Internet */
38 
39 /* Round trip timing parameters */
40 #define AGAIN 8 /* Average RTT gain = 1/8 */
41 #define LAGAIN 3 /* Log2(AGAIN) */
42 #define DGAIN 4 /* Mean deviation gain = 1/4 */
43 #define LDGAIN 2 /* log2(DGAIN) */
44 
45 #define IPPORT_DOMAIN 53
46 #define MAX_DNS_BUF_SIZE 512 /* maximum size of DNS buffer. */
47 
48 /* Header for all domain messages */
49 struct dhdr
50 {
51  uint16 id; /* Identification */
52  uint8 qr; /* Query/Response */
53 #define QUERY 0
54 #define RESPONSE 1
55  uint8 opcode;
56 #define IQUERY 1
57  uint8 aa; /* Authoratative answer */
58  uint8 tc; /* Truncation */
59  uint8 rd; /* Recursion desired */
60  uint8 ra; /* Recursion available */
61  uint8 rcode; /* Response code */
62 #define NO_ERROR 0
63 #define FORMAT_ERROR 1
64 #define SERVER_FAIL 2
65 #define NAME_ERROR 3
66 #define NOT_IMPL 4
67 #define REFUSED 5
68  uint16 qdcount; /* Question count */
69  uint16 ancount; /* Answer count */
70  uint16 nscount; /* Authority (name server) count */
71  uint16 arcount; /* Additional record count */
72 };
73 
74 static uint8 * put16(uint8 *s, uint16 i)
75 {
76  *s++ = i >> 8;
77  *s++ = i;
78 
79  return s;
80 }
81 
82 static uint16 get16(uint8 *s)
83 {
84  uint16 i;
85 
86  i = *s++ << 8;
87  i = i + *s;
88 
89  return i;
90 }
91 
92 static int16 dns_makequery(uint16 op, int8 *name, uint8 *buf, uint16 len)
93 {
94  uint8 *cp;
95  int8 *cp1;
96  int8 sname[MAX_DNS_BUF_SIZE];
97  int8 *dname;
98  uint16 p;
99  uint16 dlen;
100  static uint16 MSG_ID = 0x1122;
101 
102  cp = buf;
103 
104  MSG_ID++;
105  cp = put16(cp, MSG_ID);
106  p = (op << 11) | 0x0100; /* Recursion desired */
107  cp = put16(cp, p);
108  cp = put16(cp, 1);
109  cp = put16(cp, 0);
110  cp = put16(cp, 0);
111  cp = put16(cp, 0);
112 
113  strcpy((char*)sname, (char*)name);
114  dname = sname;
115  dlen = strlen((char*)dname);
116  for (;;)
117  {
118  /* Look for next dot */
119  cp1 = (int8*)strchr((char*)dname, '.');
120 
121  if (cp1 != NULL) len = cp1 - dname; /* More to come */
122  else len = dlen; /* Last component */
123 
124  *cp++ = len; /* Write length of component */
125  if (len == 0) break;
126 
127  /* Copy component up to (but not including) dot */
128  strncpy((char*)cp, (char*)dname, len);
129  cp += len;
130  if (cp1 == NULL)
131  {
132  *cp++ = 0; /* Last one; write null and finish */
133  break;
134  }
135  dname += len+1;
136  dlen -= len+1;
137  }
138 
139  cp = put16(cp, 0x0001); /* type */
140  cp = put16(cp, 0x0001); /* class */
141 
142  return ((int16)(cp - buf));
143 }
144 
145 static int32 parse_name(uint8 *msg, uint8 *compressed, int8 *buf, int16 len)
146 {
147  uint16 slen; /* Length of current segment */
148  uint8 * cp;
149  int32 clen = 0; /* Total length of compressed name */
150  int32 indirect = 0; /* Set if indirection encountered */
151  int32 nseg = 0; /* Total number of segments in name */
152 
153  cp = compressed;
154 
155  for (;;)
156  {
157  slen = *cp++; /* Length of this segment */
158 
159  if (!indirect) clen++;
160 
161  if ((slen & 0xc0) == 0xc0)
162  {
163  if (!indirect)
164  clen++;
165  indirect = 1;
166  /* Follow indirection */
167  cp = &msg[((slen & 0x3f)<<8) + *cp];
168  slen = *cp++;
169  }
170 
171  if (slen == 0) /* zero length == all done */
172  break;
173 
174  len -= slen + 1;
175 
176  if (len < 0) return -1;
177 
178  if (!indirect) clen += slen;
179 
180  while (slen-- != 0) *buf++ = (int8)*cp++;
181  *buf++ = '.';
182  nseg++;
183  }
184 
185  if (nseg == 0)
186  {
187  /* Root name; represent as single dot */
188  *buf++ = '.';
189  len--;
190  }
191 
192  *buf++ = '\0';
193  len--;
194 
195  return clen; /* Length of compressed message */
196 }
197 
198 static uint8 * dns_question(uint8 *msg, uint8 *cp)
199 {
200  int32 len;
201  int8 name[MAX_DNS_BUF_SIZE];
202 
203  len = parse_name(msg, cp, name, MAX_DNS_BUF_SIZE);
204 
205  DBGA("dns_question : %s", name);
206 
207  if (len == -1) return 0;
208 
209  cp += len;
210  cp += 2; /* type */
211  cp += 2; /* class */
212 
213  return cp;
214 }
215 
216 static uint8 * dns_answer(uint8 *msg, uint8 *cp, uint8 *pSip)
217 {
218  int32 len, type;
219  int8 name[MAX_DNS_BUF_SIZE];
220 
221  len = parse_name(msg, cp, name, MAX_DNS_BUF_SIZE);
222 
223  if (len == -1) return 0;
224 
225  cp += len;
226  type = get16(cp);
227  cp += 2; /* type */
228  cp += 2; /* class */
229  cp += 4; /* ttl */
230  cp += 2; /* len */
231 
232  DBGA("dns_answer : %s : %u : %.4x", name, len, type);
233 
234 
235  switch (type)
236  {
237  case TYPE_A:
238  /* Just read the address directly into the structure */
239  //Server_IP_Addr[0] = *cp++;
240  //Server_IP_Addr[1] = *cp++;
241  //Server_IP_Addr[2] = *cp++;
242  //Server_IP_Addr[3] = *cp++;
243  //Config_Msg.Sip[0] = *cp++;
244  //Config_Msg.Sip[1] = *cp++;
245  //Config_Msg.Sip[2] = *cp++;
246  //Config_Msg.Sip[3] = *cp++;
247  pSip[0] = *cp++;
248  pSip[1] = *cp++;
249  pSip[2] = *cp++;
250  pSip[3] = *cp++;
251  break;
252  case TYPE_CNAME:
253  case TYPE_MB:
254  case TYPE_MG:
255  case TYPE_MR:
256  case TYPE_NS:
257  case TYPE_PTR:
258  /* These types all consist of a single domain name */
259  /* convert it to ascii format */
260  len = parse_name(msg, cp, name, MAX_DNS_BUF_SIZE);
261  if (len == -1) return 0;
262 
263  cp += len;
264  break;
265  case TYPE_HINFO:
266  len = *cp++;
267  cp += len;
268 
269  len = *cp++;
270  cp += len;
271  break;
272  case TYPE_MX:
273  cp += 2;
274  /* Get domain name of exchanger */
275  len = parse_name(msg, cp, name, MAX_DNS_BUF_SIZE);
276  if (len == -1) return 0;
277 
278  cp += len;
279  break;
280  case TYPE_SOA:
281  /* Get domain name of name server */
282  len = parse_name(msg, cp, name, MAX_DNS_BUF_SIZE);
283  if (len == -1) return 0;
284 
285  cp += len;
286 
287  /* Get domain name of responsible person */
288  len = parse_name(msg, cp, name, MAX_DNS_BUF_SIZE);
289  if (len == -1) return 0;
290 
291  cp += len;
292 
293  cp += 4;
294  cp += 4;
295  cp += 4;
296  cp += 4;
297  cp += 4;
298  break;
299  case TYPE_TXT:
300  /* Just stash */
301  break;
302  default:
303  /* Ignore */
304  break;
305  }
306 
307  return cp;
308 }
309 
310 static int8 parseMSG(struct dhdr *pdhdr, uint8 *pbuf, uint8 *pSip)
311 {
312  uint16 tmp;
313  uint16 i;
314  uint8 * msg;
315  uint8 * cp;
316 
317  msg = pbuf;
318  memset(pdhdr, 0, sizeof(pdhdr));
319 
320  pdhdr->id = get16(&msg[0]);
321  tmp = get16(&msg[2]);
322  if (tmp & 0x8000) pdhdr->qr = 1;
323 
324  pdhdr->opcode = (tmp >> 11) & 0xf;
325 
326  if (tmp & 0x0400) pdhdr->aa = 1;
327  if (tmp & 0x0200) pdhdr->tc = 1;
328  if (tmp & 0x0100) pdhdr->rd = 1;
329  if (tmp & 0x0080) pdhdr->ra = 1;
330 
331  pdhdr->rcode = tmp & 0xf;
332  pdhdr->qdcount = get16(&msg[4]);
333  pdhdr->ancount = get16(&msg[6]);
334  pdhdr->nscount = get16(&msg[8]);
335  pdhdr->arcount = get16(&msg[10]);
336 
337  DBGA("dhdr->qdcount : %x", (uint16)pdhdr->qdcount);
338  DBGA("dhdr->ancount : %x", (uint16)pdhdr->ancount);
339  DBGA("dhdr->nscount : %x", (uint16)pdhdr->nscount);
340  DBGA("dhdr->arcount : %x", (uint16)pdhdr->arcount);
341 
342  /* Now parse the variable length sections */
343  cp = &msg[12];
344 
345  /* Question section */
346  for (i = 0; i < pdhdr->qdcount; i++)
347  {
348  cp = dns_question(msg, cp);
349  }
350 
351  /* Answer section */
352  for (i = 0; i < pdhdr->ancount; i++)
353  {
354  cp = dns_answer(msg, cp, pSip);
355  }
356 
357  /* Name server (authority) section */
358  for (i = 0; i < pdhdr->nscount; i++)
359  {
360  ;
361  }
362 
363  /* Additional section */
364  for (i = 0; i < pdhdr->arcount; i++)
365  {
366  ;
367  }
368 
369  if(pdhdr->rcode == 0) return RET_OK;
370  else return RET_NOK;
371 }
372 
383 int8 dns_query(uint8 sock, uint8 *domain, uint8 *ip)
384 {
385  struct dhdr dhp;
386  wiz_NetInfo netinfo;
387  uint8 ip_tmp[4], i = 0;
388  uint16 port;
389  int32 len, cnt;
390  uint32 tick;
391  static uint8 dns_buf[MAX_DNS_BUF_SIZE];
392 
393  tick = wizpf_get_systick();
394  srand(tick);
395  while(UDPOpen(sock, rand() % 5535 + 60000) != RET_OK) {
396  if(i++ > 3) {
397  DBGA("UDPOpen fail (%d)times", i);
398  return RET_NOK;
399  }
400  }
401 
402  i = 0;
403  GetNetInfo(&netinfo);
404  len = dns_makequery(0, (int8 *)domain, dns_buf, MAX_DNS_BUF_SIZE);
405  while((cnt = UDPSend(sock, (int8*)dns_buf, len, netinfo.dns, IPPORT_DOMAIN)) < 0) {
406  if(i++ > 3) {
407  DBGA("UDPSend fail (%d)times", i);
408  return RET_NOK;
409  }
410  }
411  if (cnt == 0) return RET_NOK; // dns fail
412 
413  cnt = 0;
414  while(1) {
415  if((len = UDPRecv(sock, (int8*)dns_buf, MAX_DNS_BUF_SIZE, ip_tmp, &port)) > 0) {
416  UDPClose(sock);
417  break;
418  }
419  Delay_ms(10);
420  if(cnt++ == 100) {
421  UDPClose(sock);
422  return RET_NOK;
423  }
424  }
425 
426  return parseMSG(&dhp, dns_buf, ip); /* Convert to local format */
427 }
428 
429 
430 
431 
432