Subversion Repositories HomeAutomation

Rev

Details | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
363 johboh 1
/*********************************************************************
2
 *
3
 *  DNS Client Module for Microchip TCP/IP Stack
4
 *   -Provides DNS resolution (client)
5
 *
6
 *********************************************************************
7
 * FileName:        DNS.c
8
 * Dependencies:    UDP, ARP, Tick
9
 * Processor:       PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F
10
 * Complier:        Microchip C18 v3.02 or higher
11
 *                  Microchip C30 v2.01 or higher
12
 * Company:         Microchip Technology, Inc.
13
 *
14
 * Software License Agreement
15
 *
16
 * This software is owned by Microchip Technology Inc. ("Microchip")
17
 * and is supplied to you for use exclusively as described in the
18
 * associated software agreement.  This software is protected by
19
 * software and other intellectual property laws.  Any use in
20
 * violation of the software license may subject the user to criminal
21
 * sanctions as well as civil liability.  Copyright 2006 Microchip
22
 * Technology Inc.  All rights reserved.
23
 *
24
 * This software is provided "AS IS."  MICROCHIP DISCLAIMS ALL
25
 * WARRANTIES, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, NOT LIMITED
26
 * TO MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
27
 * INFRINGEMENT.  Microchip shall in no event be liable for special,
28
 * incidental, or consequential damages.
29
 *
30
 *
31
 * Author               Date    Comment
32
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
33
 * Howard Schlunder     7/31/06 Original
34
 ********************************************************************/
35
#define THIS_IS_DNS
36
 
37
#include "..\Include\Compiler.h"
38
#include "..\Include\UDP.h"
39
#include "..\Include\Tick.h"
40
#include "..\Include\ARP.h"
41
#include "..\Include\ARPTsk.h"
42
#include "..\Include\DNS.h"
43
#include "..\Include\Helpers.h"
44
 
45
#if defined(STACK_USE_DNS)
46
 
47
#define DNS_PORT        53
48
#define DNS_TIMEOUT     (TICK_1S*2)
49
 
50
 
51
static BYTE *DNSHostName;
52
static enum
53
{
54
    DNS_HOME = 0,
55
    DNS_RESOLVE_ARP,
56
    DNS_OPEN_SOCKET,
57
    DNS_QUERY,
58
    DNS_GET_RESULT,
59
    DNS_DONE
60
} smDNS = DNS_DONE;
61
 
62
typedef struct _DNS_HEADER
63
{
64
    WORD_VAL TransactionID;
65
    WORD_VAL Flags;
66
    WORD_VAL Questions;
67
    WORD_VAL Answers;
68
    WORD_VAL AuthoritativeRecords;
69
    WORD_VAL AdditionalRecords;
70
} DNS_HEADER;
71
 
72
typedef struct _DNS_ANSWER_HEADER
73
{
74
    WORD_VAL    ResponseName;
75
    WORD_VAL    ResponseType;
76
    WORD_VAL    ResponseClass;
77
    DWORD_VAL   ResponseTTL;
78
    WORD_VAL    ResponseLen;
79
} DNS_ANSWER_HEADER;
80
 
81
static void DNSPutString(BYTE *String);
82
static void DNSGetString(BYTE *String);
83
 
84
/*********************************************************************
85
 * Function:        void DNSResolve(BYTE *Hostname)
86
 *
87
 * PreCondition:    Stack is initialized()
88
 *
89
 * Input:           *Hostname: Null terminated string specifying the
90
 *                             host address to resolve to an IP
91
 *                             address.
92
 *
93
 * Output:          None
94
 *
95
 * Side Effects:    None
96
 *
97
 * Overview:        Call DNSIsResolved() until the host is resolved.
98
 *
99
 * Note:            A UDP socket must be available before this
100
 *                  function is called.  It is freed at the end of
101
 *                  the resolution.  MAX_UDP_SOCKETS may need to be
102
 *                  increased if other modules use UDP sockets.
103
 *
104
 *                  You must not modify *Hostname until DNSIsResolved()
105
 *                  returns TRUE.
106
 ********************************************************************/
107
void DNSResolve(BYTE *Hostname)
108
{
109
    DNSHostName = Hostname;
110
    smDNS = DNS_HOME;
111
}
112
 
113
 
114
/*********************************************************************
115
 * Function:        BOOL DNSIsResolved(IP_ADDR *HostIP)
116
 *
117
 * PreCondition:    DNSResolve() was called.
118
 *
119
 * Input:           HostIP: Pointer to IP_ADDR structure to store the
120
 *                          returned host IP address when DNS
121
 *                          resolution is complete.
122
 *
123
 * Output:          *HostIP, 4 byte IP address
124
 *
125
 * Side Effects:    None
126
 *
127
 * Overview:        Call DNSIsResolved() until the host is resolved.
128
 *
129
 * Note:            You cannot start two DNS resolution proceedures
130
 *                  concurrently.
131
 *
132
 *                  You must not modify *Hostname until DNSIsResolved()
133
 *                  returns TRUE.
134
 ********************************************************************/
135
BOOL DNSIsResolved(IP_ADDR *HostIP)
136
{
137
    static UDP_SOCKET   MySocket;
138
    static NODE_INFO    Remote;
139
    static TICK         StartTime;
140
    BYTE                i;
141
    WORD_VAL            w;
142
    DNS_HEADER          DNSHeader;
143
    DNS_ANSWER_HEADER   DNSAnswerHeader;
144
 
145
    switch(smDNS)
146
    {
147
        case DNS_HOME:
148
            ARPResolve(&AppConfig.PrimaryDNSServer);
149
            StartTime = tickGet();
150
            smDNS++;
151
            break;
152
        case DNS_RESOLVE_ARP:
153
            if(!ARPIsResolved(&AppConfig.PrimaryDNSServer, &Remote.MACAddr))
154
            {
155
                if(tickGet() - StartTime > DNS_TIMEOUT)
156
                {
157
                    smDNS--;
158
                }
159
                break;
160
            }
161
            Remote.IPAddr.Val = AppConfig.PrimaryDNSServer.Val;
162
            smDNS++;
163
            // No need to break, we can immediately start resolution
164
 
165
        case DNS_OPEN_SOCKET:
166
            MySocket = UDPOpen(0, &Remote, DNS_PORT);
167
            if(MySocket == INVALID_UDP_SOCKET)
168
                break;
169
 
170
            smDNS++;
171
            // No need to break, we can immediately start resolution
172
 
173
        case DNS_QUERY:
174
            if(!UDPIsPutReady(MySocket))
175
                break;
176
 
177
            // Put DNS query here
178
            UDPPut(0x12);       // User chosen ID
179
            UDPPut(0x34);
180
            UDPPut(0x01);       // Standard query with recursion
181
            UDPPut(0x00);  
182
            UDPPut(0x00);       // 0x0001 questions
183
            UDPPut(0x01);
184
            UDPPut(0x00);       // 0x0000 answers
185
            UDPPut(0x00);
186
            UDPPut(0x00);       // 0x0000 name server resource records
187
            UDPPut(0x00);
188
            UDPPut(0x00);       // 0x0000 additional records
189
            UDPPut(0x00);
190
 
191
            // Put hostname string to resolve
192
            DNSPutString(DNSHostName);
193
 
194
            UDPPut(0x00);       // Type: A (host address)
195
            UDPPut(0x01);
196
            UDPPut(0x00);       // Class: IN (Internet)
197
            UDPPut(0x01);
198
 
199
            UDPFlush();
200
            StartTime = tickGet();
201
            smDNS++;
202
            break;
203
 
204
        case DNS_GET_RESULT:
205
            if(!UDPIsGetReady(MySocket))
206
            {
207
                if(tickGet() - StartTime > DNS_TIMEOUT)
208
                {
209
                    smDNS--;
210
                }
211
                break;
212
            }
213
 
214
            // Retrieve the DNS header and de-big-endian it
215
            UDPGet(&DNSHeader.TransactionID.v[1]);
216
            UDPGet(&DNSHeader.TransactionID.v[0]);
217
            UDPGet(&DNSHeader.Flags.v[1]);
218
            UDPGet(&DNSHeader.Flags.v[0]);
219
            UDPGet(&DNSHeader.Questions.v[1]);
220
            UDPGet(&DNSHeader.Questions.v[0]);
221
            UDPGet(&DNSHeader.Answers.v[1]);
222
            UDPGet(&DNSHeader.Answers.v[0]);
223
            UDPGet(&DNSHeader.AuthoritativeRecords.v[1]);
224
            UDPGet(&DNSHeader.AuthoritativeRecords.v[0]);
225
            UDPGet(&DNSHeader.AdditionalRecords.v[1]);
226
            UDPGet(&DNSHeader.AdditionalRecords.v[0]);
227
 
228
            // Remove all questions
229
            while(DNSHeader.Questions.Val--)
230
            {
231
                DNSGetString(NULL);
232
                UDPGet(&w.v[1]);        // Question type
233
                UDPGet(&w.v[0]);
234
                UDPGet(&w.v[1]);        // Question class
235
                UDPGet(&w.v[0]);
236
            }
237
 
238
            // Scan through answers
239
            while(DNSHeader.Answers.Val--)
240
            {
241
                UDPGet(&DNSAnswerHeader.ResponseName.v[1]);     // Response name
242
                UDPGet(&DNSAnswerHeader.ResponseName.v[0]);
243
                UDPGet(&DNSAnswerHeader.ResponseType.v[1]);     // Response type
244
                UDPGet(&DNSAnswerHeader.ResponseType.v[0]);
245
                UDPGet(&DNSAnswerHeader.ResponseClass.v[1]);    // Response class
246
                UDPGet(&DNSAnswerHeader.ResponseClass.v[0]);
247
                UDPGet(&DNSAnswerHeader.ResponseTTL.v[3]);      // Time to live
248
                UDPGet(&DNSAnswerHeader.ResponseTTL.v[2]);
249
                UDPGet(&DNSAnswerHeader.ResponseTTL.v[1]);
250
                UDPGet(&DNSAnswerHeader.ResponseTTL.v[0]);
251
                UDPGet(&DNSAnswerHeader.ResponseLen.v[1]);      // Response length
252
                UDPGet(&DNSAnswerHeader.ResponseLen.v[0]);
253
 
254
                // Make sure that this is a 4 byte IP address, response type A, class 1
255
                // Check if this is Type A
256
                if( DNSAnswerHeader.ResponseType.Val    == 0x0001 &&
257
                    DNSAnswerHeader.ResponseClass.Val   == 0x0001 && // Internet class
258
                    DNSAnswerHeader.ResponseLen.Val     == 0x0004)
259
                {
260
                    UDPGet(&HostIP->v[0]);
261
                    UDPGet(&HostIP->v[1]);
262
                    UDPGet(&HostIP->v[2]);
263
                    UDPGet(&HostIP->v[3]);
264
                    break;
265
                }
266
                else
267
                {
268
                    while(DNSAnswerHeader.ResponseLen.Val--)
269
                    {
270
                        UDPGet(&i);
271
                    }
272
                }
273
            }
274
 
275
            UDPDiscard();
276
            UDPClose(MySocket);
277
            MySocket = INVALID_UDP_SOCKET;
278
            smDNS++;
279
            // No need to break, we are done and need to return TRUE
280
 
281
        case DNS_DONE:
282
            return TRUE;
283
    }
284
 
285
    return FALSE;
286
}
287
 
288
static void DNSPutString(BYTE *String)
289
{
290
    BYTE *RightPtr;
291
    BYTE i;
292
    BYTE Len;
293
 
294
    RightPtr = String;
295
 
296
    while(1)
297
    {
298
        do
299
        {
300
            i = *RightPtr++;
301
        } while((i != 0x00) && (i != '.') && (i != '/'));
302
 
303
        // Put the length parameter
304
        Len = (BYTE)(RightPtr-String-1);
305
        UDPPut(Len);
306
        while(Len--)
307
        {
308
            UDPPut(*String++);
309
        }
310
        if(i == 0x00 || i == '/')
311
            break;
312
 
313
        // Skip over the '.' in the input string
314
        String++;
315
    }
316
 
317
    // Put the string terminator character
318
    UDPPut(0x00);
319
}
320
 
321
static void DNSGetString(BYTE *String)
322
{
323
    BYTE i;
324
    BYTE j;
325
 
326
    if(String == NULL)
327
    {
328
        UDPGet(&i);
329
        while(i)
330
        {
331
            while(i--)
332
            {
333
                UDPGet(&j);
334
            }
335
            UDPGet(&i);
336
        }
337
    }
338
    else
339
    {
340
        UDPGet(&i);
341
        while(i)
342
        {
343
            while(i--)
344
            {
345
                UDPGet(String);
346
                String++;
347
            }
348
            UDPGet(&i);
349
        }
350
    }
351
}
352
 
353
 
354
#endif  //#if defined(STACK_USE_DNS)