/[H8]/trunk/docs/Microchip TCP_IP stack/TCPIP Stack/DNS.c
ViewVC logotype

Annotation of /trunk/docs/Microchip TCP_IP stack/TCPIP Stack/DNS.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 15 - (hide annotations) (download)
Thu Apr 19 09:01:15 2007 UTC (17 years, 3 months ago) by hedin
File MIME type: text/plain
File size: 16530 byte(s)
added the TCP/IP stack, source code.
1 hedin 15 /*********************************************************************
2     *
3     * Domain Name System (DNS) Client
4     * Module for Microchip TCP/IP Stack
5     * -Provides hostname to IP address translation
6     * -Reference: RFC 1035
7     *
8     *********************************************************************
9     * FileName: DNS.c
10     * Dependencies: UDP, ARP, Tick
11     * Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F
12     * Complier: Microchip C18 v3.02 or higher
13     * Microchip C30 v2.05 or higher
14     * Company: Microchip Technology, Inc.
15     *
16     * Software License Agreement
17     *
18     * Copyright © 2002-2007 Microchip Technology Inc. All rights
19     * reserved.
20     *
21     * Microchip licenses to you the right to use, modify, copy, and
22     * distribute:
23     * (i) the Software when embedded on a Microchip microcontroller or
24     * digital signal controller product (“Device”) which is
25     * integrated into Licensee’s product; or
26     * (ii) ONLY the Software driver source files ENC28J60.c and
27     * ENC28J60.h ported to a non-Microchip device used in
28     * conjunction with a Microchip ethernet controller for the
29     * sole purpose of interfacing with the ethernet controller.
30     *
31     * You should refer to the license agreement accompanying this
32     * Software for additional information regarding your rights and
33     * obligations.
34     *
35     * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED “AS IS” WITHOUT
36     * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
37     * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
38     * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
39     * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
40     * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
41     * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
42     * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
43     * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
44     * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
45     * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
46     *
47     *
48     * Author Date Comment
49     *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
50     * Howard Schlunder 7/31/06 Original
51     * Howard Schlunder 10/09/06 Added DNSBeginUsage(), DNSEndUsage()
52     * module ownership semaphore
53     ********************************************************************/
54     #define __DNS_C
55    
56     #include "TCPIP Stack/TCPIP.h"
57    
58     #if defined(STACK_USE_DNS)
59    
60    
61     #define DNS_PORT 53u
62     #define DNS_TIMEOUT (TICK_SECOND*2)
63    
64    
65    
66     static UDP_SOCKET MySocket = INVALID_UDP_SOCKET;
67     static BYTE *DNSHostName;
68     static ROM BYTE *DNSHostNameROM;
69     static BYTE RecordType;
70     static union
71     {
72     BYTE Val;
73     struct
74     {
75     unsigned char DNSInUse : 1;
76     unsigned char AddressValid : 1;
77     unsigned char filler : 6;
78     } bits;
79     } Flags = {0x00};
80     static enum
81     {
82     DNS_HOME = 0,
83     DNS_RESOLVE_ARP,
84     DNS_OPEN_SOCKET,
85     DNS_QUERY,
86     DNS_GET_RESULT,
87     DNS_DONE
88     } smDNS = DNS_DONE;
89    
90     typedef struct _DNS_HEADER
91     {
92     WORD_VAL TransactionID;
93     WORD_VAL Flags;
94     WORD_VAL Questions;
95     WORD_VAL Answers;
96     WORD_VAL AuthoritativeRecords;
97     WORD_VAL AdditionalRecords;
98     } DNS_HEADER;
99    
100     typedef struct _DNS_ANSWER_HEADER
101     {
102     WORD_VAL ResponseName;
103     WORD_VAL ResponseType;
104     WORD_VAL ResponseClass;
105     DWORD_VAL ResponseTTL;
106     WORD_VAL ResponseLen;
107     } DNS_ANSWER_HEADER;
108    
109     static void DNSPutString(BYTE *String);
110     static void DNSPutROMString(ROM BYTE *String);
111     static void DNSGetString(BYTE *String);
112    
113    
114     /*********************************************************************
115     * Function: BOOL DNSBeginUsage(void)
116     *
117     * PreCondition: Stack is initialized()
118     *
119     * Input: None
120     *
121     * Output: TRUE: If no DNS resolution operations are in progress and this application has successfully taken ownership of the DNS module
122     * FALSE: If the DNS module is currently being used by some other module. Call DNSBeginUsage() some time later (after returning to the main() program loop).
123     *
124     * Side Effects: None
125     *
126     * Overview: Call DNSBeginUsage() and make sure it returns TRUE before calling any DNS APIs. Call DNSEndUsage() when this application no longer needs the DNS module so that other applications may make use of it.
127     *
128     * Note: None
129     ********************************************************************/
130     BOOL DNSBeginUsage(void)
131     {
132     if(Flags.bits.DNSInUse)
133     return FALSE;
134    
135     Flags.bits.DNSInUse = TRUE;
136     return TRUE;
137     }
138    
139    
140     /*********************************************************************
141     * Function: BOOL DNSEndUsage(void)
142     *
143     * PreCondition: DNSBeginUsage() returned TRUE on a previous call.
144     *
145     * Input: None
146     *
147     * Output: TRUE: If the address to the host name was
148     * successfully resolved
149     * FALSE: If the DNS failed or address does not
150     * exists. The contents of *Hostname are
151     * unchanged.
152     *
153     * Side Effects: None
154     *
155     * Overview: Call DNSBeginUsage() and make sure it returns
156     * TRUE before calling any DNS APIs. Call
157     * DNSEndUsage() when this application no longer
158     * needs the DNS module so that other applications
159     * may make use of it.
160     *
161     * Note: None
162     ********************************************************************/
163     BOOL DNSEndUsage(void)
164     {
165     if(MySocket != INVALID_UDP_SOCKET)
166     {
167     UDPClose(MySocket);
168     MySocket = INVALID_UDP_SOCKET;
169     }
170     smDNS = DNS_DONE;
171     Flags.bits.DNSInUse = FALSE;
172    
173     return Flags.bits.AddressValid;
174     }
175    
176    
177     /*********************************************************************
178     * Function: void DNSResolve(BYTE *Hostname, BYTE RecordType)
179     *
180     * PreCondition: Stack is initialized()
181     *
182     * Input: *Hostname: Null terminated string specifying the
183     * host address to resolve to an IP
184     * address.
185     * Type: DNS_TYPE_A (1d): Host Address (normal IP address)
186     * DNS_TYPE_MX (15d): Mail eXchange
187     * All other values are reserved
188     *
189     * Output: None
190     *
191     * Side Effects: None
192     *
193     * Overview: Call DNSIsResolved() until the host is resolved.
194     *
195     * Note: A UDP socket must be available before this
196     * function is called. It is freed at the end of
197     * the resolution. MAX_UDP_SOCKETS may need to be
198     * increased if other modules use UDP sockets.
199     *
200     * You must not modify *Hostname until DNSIsResolved()
201     * returns TRUE.
202     ********************************************************************/
203     void DNSResolve(BYTE *Hostname, BYTE Type)
204     {
205     DNSHostName = Hostname;
206     DNSHostNameROM = NULL;
207     smDNS = DNS_HOME;
208     RecordType = Type;
209     Flags.bits.AddressValid = FALSE;
210     }
211    
212     void DNSResolveROM(ROM BYTE *Hostname, BYTE Type)
213     {
214     DNSHostName = NULL;
215     DNSHostNameROM = Hostname;
216     smDNS = DNS_HOME;
217     RecordType = Type;
218     Flags.bits.AddressValid = FALSE;
219     }
220    
221    
222     /*********************************************************************
223     * Function: BOOL DNSIsResolved(IP_ADDR *HostIP)
224     *
225     * PreCondition: DNSResolve() was called.
226     *
227     * Input: HostIP: Pointer to IP_ADDR structure to store the
228     * returned host IP address when DNS
229     * resolution is complete.
230     *
231     * Output: *HostIP, 4 byte IP address
232     *
233     * Side Effects: None
234     *
235     * Overview: Call DNSIsResolved() until the host is resolved.
236     *
237     * Note: You cannot start two DNS resolution proceedures
238     * concurrently.
239     *
240     * You must not modify *Hostname until DNSIsResolved()
241     * returns TRUE.
242     ********************************************************************/
243     BOOL DNSIsResolved(IP_ADDR *HostIP)
244     {
245     static NODE_INFO Remote;
246     static TICK StartTime;
247     static WORD_VAL SentTransactionID __attribute__((persistent));
248     BYTE i;
249     WORD_VAL w;
250     DNS_HEADER DNSHeader;
251     DNS_ANSWER_HEADER DNSAnswerHeader;
252    
253     switch(smDNS)
254     {
255     case DNS_HOME:
256     ARPResolve(&AppConfig.PrimaryDNSServer);
257     StartTime = TickGet();
258     smDNS++;
259     break;
260    
261     case DNS_RESOLVE_ARP:
262     if(!ARPIsResolved(&AppConfig.PrimaryDNSServer, &Remote.MACAddr))
263     {
264     if(TickGet() - StartTime > DNS_TIMEOUT)
265     {
266     smDNS--;
267     }
268     break;
269     }
270     Remote.IPAddr.Val = AppConfig.PrimaryDNSServer.Val;
271     smDNS++;
272     // No need to break, we can immediately open a socket
273    
274     case DNS_OPEN_SOCKET:
275     MySocket = UDPOpen(0, &Remote, DNS_PORT);
276     if(MySocket == INVALID_UDP_SOCKET)
277     break;
278    
279     smDNS++;
280     // No need to break, we can immediately start resolution
281    
282     case DNS_QUERY:
283     if(!UDPIsPutReady(MySocket))
284     break;
285    
286     // Put DNS query here
287     SentTransactionID.Val++;
288     UDPPut(SentTransactionID.v[1]);// User chosen transaction ID
289     UDPPut(SentTransactionID.v[0]);
290     UDPPut(0x01); // Standard query with recursion
291     UDPPut(0x00);
292     UDPPut(0x00); // 0x0001 questions
293     UDPPut(0x01);
294     UDPPut(0x00); // 0x0000 answers
295     UDPPut(0x00);
296     UDPPut(0x00); // 0x0000 name server resource records
297     UDPPut(0x00);
298     UDPPut(0x00); // 0x0000 additional records
299     UDPPut(0x00);
300    
301     // Put hostname string to resolve
302     if(DNSHostName)
303     DNSPutString(DNSHostName);
304     else
305     DNSPutROMString(DNSHostNameROM);
306    
307     UDPPut(0x00); // Type: DNS_TYPE_A A (host address) or DNS_TYPE_MX for mail exchange
308     UDPPut(RecordType);
309     UDPPut(0x00); // Class: IN (Internet)
310     UDPPut(0x01);
311    
312     UDPFlush();
313     StartTime = TickGet();
314     smDNS++;
315     break;
316    
317     case DNS_GET_RESULT:
318     if(!UDPIsGetReady(MySocket))
319     {
320     if(TickGet() - StartTime > DNS_TIMEOUT)
321     {
322     smDNS--;
323     }
324     break;
325     }
326    
327     // Retrieve the DNS header and de-big-endian it
328     UDPGet(&DNSHeader.TransactionID.v[1]);
329     UDPGet(&DNSHeader.TransactionID.v[0]);
330    
331     // Throw this packet away if it isn't in response to our last query
332     if(DNSHeader.TransactionID.Val != SentTransactionID.Val)
333     {
334     UDPDiscard();
335     break;
336     }
337    
338     UDPGet(&DNSHeader.Flags.v[1]);
339     UDPGet(&DNSHeader.Flags.v[0]);
340     UDPGet(&DNSHeader.Questions.v[1]);
341     UDPGet(&DNSHeader.Questions.v[0]);
342     UDPGet(&DNSHeader.Answers.v[1]);
343     UDPGet(&DNSHeader.Answers.v[0]);
344     UDPGet(&DNSHeader.AuthoritativeRecords.v[1]);
345     UDPGet(&DNSHeader.AuthoritativeRecords.v[0]);
346     UDPGet(&DNSHeader.AdditionalRecords.v[1]);
347     UDPGet(&DNSHeader.AdditionalRecords.v[0]);
348    
349     // Remove all questions
350     while(DNSHeader.Questions.Val--)
351     {
352     DNSGetString(NULL);
353     UDPGet(&w.v[1]); // Question type
354     UDPGet(&w.v[0]);
355     UDPGet(&w.v[1]); // Question class
356     UDPGet(&w.v[0]);
357     }
358    
359     // Scan through answers
360     while(DNSHeader.Answers.Val--)
361     {
362     UDPGet(&DNSAnswerHeader.ResponseName.v[1]); // Response name
363     UDPGet(&DNSAnswerHeader.ResponseName.v[0]);
364     UDPGet(&DNSAnswerHeader.ResponseType.v[1]); // Response type
365     UDPGet(&DNSAnswerHeader.ResponseType.v[0]);
366     UDPGet(&DNSAnswerHeader.ResponseClass.v[1]); // Response class
367     UDPGet(&DNSAnswerHeader.ResponseClass.v[0]);
368     UDPGet(&DNSAnswerHeader.ResponseTTL.v[3]); // Time to live
369     UDPGet(&DNSAnswerHeader.ResponseTTL.v[2]);
370     UDPGet(&DNSAnswerHeader.ResponseTTL.v[1]);
371     UDPGet(&DNSAnswerHeader.ResponseTTL.v[0]);
372     UDPGet(&DNSAnswerHeader.ResponseLen.v[1]); // Response length
373     UDPGet(&DNSAnswerHeader.ResponseLen.v[0]);
374    
375     // Make sure that this is a 4 byte IP address, response type A or MX, class 1
376     // Check if this is Type A or MX
377     if( DNSAnswerHeader.ResponseType.Val == 0x0001u &&
378     DNSAnswerHeader.ResponseClass.Val == 0x0001u && // Internet class
379     DNSAnswerHeader.ResponseLen.Val == 0x0004u)
380     {
381     Flags.bits.AddressValid = TRUE;
382     UDPGet(&HostIP->v[0]);
383     UDPGet(&HostIP->v[1]);
384     UDPGet(&HostIP->v[2]);
385     UDPGet(&HostIP->v[3]);
386     goto DoneSearchingRecords;
387     }
388     else
389     {
390     while(DNSAnswerHeader.ResponseLen.Val--)
391     {
392     UDPGet(&i);
393     }
394     }
395     }
396    
397     // Remove all Authoritative Records
398     while(DNSHeader.AuthoritativeRecords.Val--)
399     {
400     UDPGet(&DNSAnswerHeader.ResponseName.v[1]); // Response name
401     UDPGet(&DNSAnswerHeader.ResponseName.v[0]);
402     UDPGet(&DNSAnswerHeader.ResponseType.v[1]); // Response type
403     UDPGet(&DNSAnswerHeader.ResponseType.v[0]);
404     UDPGet(&DNSAnswerHeader.ResponseClass.v[1]); // Response class
405     UDPGet(&DNSAnswerHeader.ResponseClass.v[0]);
406     UDPGet(&DNSAnswerHeader.ResponseTTL.v[3]); // Time to live
407     UDPGet(&DNSAnswerHeader.ResponseTTL.v[2]);
408     UDPGet(&DNSAnswerHeader.ResponseTTL.v[1]);
409     UDPGet(&DNSAnswerHeader.ResponseTTL.v[0]);
410     UDPGet(&DNSAnswerHeader.ResponseLen.v[1]); // Response length
411     UDPGet(&DNSAnswerHeader.ResponseLen.v[0]);
412    
413     // Make sure that this is a 4 byte IP address, response type A or MX, class 1
414     // Check if this is Type A
415     if( DNSAnswerHeader.ResponseType.Val == 0x0001u &&
416     DNSAnswerHeader.ResponseClass.Val == 0x0001u && // Internet class
417     DNSAnswerHeader.ResponseLen.Val == 0x0004u)
418     {
419     Flags.bits.AddressValid = TRUE;
420     UDPGet(&HostIP->v[0]);
421     UDPGet(&HostIP->v[1]);
422     UDPGet(&HostIP->v[2]);
423     UDPGet(&HostIP->v[3]);
424     goto DoneSearchingRecords;
425     }
426     else
427     {
428     while(DNSAnswerHeader.ResponseLen.Val--)
429     {
430     UDPGet(&i);
431     }
432     }
433     }
434    
435     // Remove all Additional Records
436     while(DNSHeader.AdditionalRecords.Val--)
437     {
438     UDPGet(&DNSAnswerHeader.ResponseName.v[1]); // Response name
439     UDPGet(&DNSAnswerHeader.ResponseName.v[0]);
440     UDPGet(&DNSAnswerHeader.ResponseType.v[1]); // Response type
441     UDPGet(&DNSAnswerHeader.ResponseType.v[0]);
442     UDPGet(&DNSAnswerHeader.ResponseClass.v[1]); // Response class
443     UDPGet(&DNSAnswerHeader.ResponseClass.v[0]);
444     UDPGet(&DNSAnswerHeader.ResponseTTL.v[3]); // Time to live
445     UDPGet(&DNSAnswerHeader.ResponseTTL.v[2]);
446     UDPGet(&DNSAnswerHeader.ResponseTTL.v[1]);
447     UDPGet(&DNSAnswerHeader.ResponseTTL.v[0]);
448     UDPGet(&DNSAnswerHeader.ResponseLen.v[1]); // Response length
449     UDPGet(&DNSAnswerHeader.ResponseLen.v[0]);
450    
451     // Make sure that this is a 4 byte IP address, response type A or MX, class 1
452     // Check if this is Type A
453     if( DNSAnswerHeader.ResponseType.Val == 0x0001u &&
454     DNSAnswerHeader.ResponseClass.Val == 0x0001u && // Internet class
455     DNSAnswerHeader.ResponseLen.Val == 0x0004u)
456     {
457     Flags.bits.AddressValid = TRUE;
458     UDPGet(&HostIP->v[0]);
459     UDPGet(&HostIP->v[1]);
460     UDPGet(&HostIP->v[2]);
461     UDPGet(&HostIP->v[3]);
462     goto DoneSearchingRecords;
463     }
464     else
465     {
466     while(DNSAnswerHeader.ResponseLen.Val--)
467     {
468     UDPGet(&i);
469     }
470     }
471     }
472    
473     DoneSearchingRecords:
474    
475     UDPDiscard();
476     UDPClose(MySocket);
477     MySocket = INVALID_UDP_SOCKET;
478     smDNS++;
479     // No need to break, we are done and need to return TRUE
480    
481     case DNS_DONE:
482     return TRUE;
483     }
484    
485     return FALSE;
486     }
487    
488     static void DNSPutString(BYTE *String)
489     {
490     BYTE *RightPtr;
491     BYTE i;
492     BYTE Len;
493    
494     RightPtr = String;
495    
496     while(1)
497     {
498     do
499     {
500     i = *RightPtr++;
501     } while((i != 0x00u) && (i != '.') && (i != '/') && (i != ',') && (i != '>'));
502    
503     // Put the length parameter
504     Len = (BYTE)(RightPtr-String-1);
505     UDPPut(Len);
506     while(Len--)
507     {
508     UDPPut(*String++);
509     }
510     if(i == 0x00u || i == '/' || i == ',' || i == '>')
511     break;
512    
513     // Skip over the '.' in the input string
514     String++;
515     }
516    
517     // Put the string terminator character
518     UDPPut(0x00);
519     }
520    
521     static void DNSPutROMString(ROM BYTE *String)
522     {
523     ROM BYTE *RightPtr;
524     BYTE i;
525     BYTE Len;
526    
527     RightPtr = String;
528    
529     while(1)
530     {
531     do
532     {
533     i = *RightPtr++;
534     } while((i != 0x00u) && (i != '.') && (i != '/') && (i != ',') && (i != '>'));
535    
536     // Put the length parameter
537     Len = (BYTE)(RightPtr-String-1);
538     UDPPut(Len);
539     UDPPutROMArray(String, Len);
540     String += Len + 1;
541    
542     if(i == 0x00u || i == '/' || i == ',' || i == '>')
543     break;
544     }
545    
546     // Put the string terminator character
547     UDPPut(0x00);
548     }
549    
550    
551     static void DNSGetString(BYTE *String)
552     {
553     BYTE i;
554     BYTE j;
555    
556     if(String == NULL)
557     {
558     UDPGet(&i);
559     while(i)
560     {
561     while(i--)
562     {
563     UDPGet(&j);
564     }
565     UDPGet(&i);
566     }
567     }
568     else
569     {
570     UDPGet(&i);
571     while(i)
572     {
573     while(i--)
574     {
575     UDPGet(String);
576     String++;
577     }
578     UDPGet(&i);
579     }
580     }
581     }
582    
583    
584     #endif //#if defined(STACK_USE_DNS)

  ViewVC Help
Powered by ViewVC 1.1.20