Subversion Repositories HomeAutomation

Rev

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

Rev Author Line No. Line
363 johboh 1
/*********************************************************************
2
 *
3
 *                  DHCP Module for Microchip TCP/IP Stack
4
 *
5
 *********************************************************************
6
 * FileName:        DHCP.c
7
 * Dependencies:    StackTsk.h
8
 *                  UDP.h
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
 * Nilesh Rajbharti     3/21/01  Original        (Rev 1.0)
34
 * Nilesh Rajbharti     7/10/02  Explicitly initialized tempIPAddress
35
 *                                               (Rev 2.11)
36
 * Nilesh Rajbharti     5/16/03 Increased DHCP_TIMEOUT to 2 seconds.
37
 * Nilesh Rajbharti     5/16/03 Fixed SM_DHCP_BROADCAST logic
38
 *                              where UDPPut was called before setting
39
 *                              active socket.
40
 * Robert Sloan         5/29/03 Improved DHCP State machine to handle
41
 *                              NAK and renew existing IP address.
42
 * Nilesh Rajbharti     8/15/03 Modified _DHCPRecieve() to check for
43
 *                              chaddr field before accpting the packet.
44
 *                              Fixed DHCPTask() where it would not
45
 *                              reply to first OFFER.
46
 * Nilesh Rajbharti     3/1/04  Used tickDiff in DHCPTask() "bind"
47
 *                              state to adjust for irregular TICK_SECOND
48
 *                              Without this logic, actual lease time count
49
 *                              down may be incorrect.
50
 * Howard Schlunder     5/11/06 Fixed tickDiff usage, reducing
51
 *                              accumulated timing error.  Fixed DHCP
52
 *                              state machine requesting IP 0.0.0.0
53
 *                              after lease expiration.
54
 * Howard Schlunder     6/01/06 Added DHCPState.bits.bOfferReceived flag to
55
 *                              allow operation on networks with multiple
56
 *                              DHCP servers offering multiple addresses
57
 * Howard Schlunder     8/01/06 Added DNS server option to DHCP request,
58
 *                              untested Host Name option to DHCP request
59
 ********************************************************************/
60
#define THIS_IS_DHCP
61
 
62
#include "..\Include\StackTsk.h"
63
 
64
#if defined(STACK_USE_DHCP)
65
 
66
#include "..\Include\DHCP.h"
67
#include "..\Include\UDP.h"
68
#include "..\Include\Tick.h"
69
 
70
 
71
#if defined(STACK_USE_SLIP)
72
    #error DHCP module is not available when SLIP is used.
73
#endif
74
 
75
 
76
#define DHCP_TIMEOUT                    (TICK)(2L * TICK_SECOND)
77
 
78
 
79
#define DHCP_CLIENT_PORT                (68u)
80
#define DHCP_SERVER_PORT                (67u)
81
 
82
#define BOOT_REQUEST                    (1u)
83
#define BOOT_REPLY                      (2u)
84
#define HW_TYPE                         (1u)
85
#define LEN_OF_HW_TYPE                  (6u)
86
 
87
#define DHCP_MESSAGE_TYPE               (53u)
88
#define DHCP_MESSAGE_TYPE_LEN           (1u)
89
 
90
#define DHCP_UNKNOWN_MESSAGE            (0u)
91
 
92
#define DHCP_DISCOVER_MESSAGE           (1u)
93
#define DHCP_OFFER_MESSAGE              (2u)
94
#define DHCP_REQUEST_MESSAGE            (3u)
95
#define DHCP_DECLINE_MESSAGE            (4u)
96
#define DHCP_ACK_MESSAGE                (5u)
97
#define DHCP_NAK_MESSAGE                (6u)
98
#define DHCP_RELEASE_MESSAGE            (7u)
99
 
100
#define DHCP_SERVER_IDENTIFIER          (54u)
101
#define DHCP_SERVER_IDENTIFIER_LEN      (4u)
102
 
103
#define DHCP_PARAM_REQUEST_LIST         (55u)
104
#define DHCP_PARAM_REQUEST_LIST_LEN     (4u)
105
#define DHCP_PARAM_REQUEST_IP_ADDRESS       (50u)
106
#define DHCP_PARAM_REQUEST_IP_ADDRESS_LEN   (4u)
107
#define DHCP_SUBNET_MASK                (1u)
108
#define DHCP_ROUTER                     (3u)
109
#define DHCP_DNS                        (6u)
110
#define DHCP_HOST_NAME                  (12u)
111
#define DHCP_IP_LEASE_TIME              (51u)
112
#define DHCP_END_OPTION                 (255u)
113
 
114
#define HALF_HOUR                       (WORD)((WORD)60 * (WORD)30)
115
 
116
SM_DHCP  smDHCPState = SM_DHCP_INIT_FIRST_TIME;
117
static UDP_SOCKET DHCPSocket = INVALID_UDP_SOCKET;
118
 
119
 
120
DHCP_STATE DHCPState = { 0x00 };
121
 
122
static DWORD_VAL DHCPServerID;
123
static DWORD_VAL DHCPLeaseTime;
124
 
125
static IP_ADDR tempIPAddress;
126
static IP_ADDR tempGateway;
127
static IP_ADDR tempMask;
128
#if defined(STACK_USE_DNS)
129
static IP_ADDR tempDNS;
130
#endif
131
//static BYTE tempHostName[16];
132
 
133
static union
134
{
135
    struct
136
    {
137
        char IPAddress:1;
138
        char Gateway:1;
139
        char Mask:1;
140
        char DNS:1;
141
        char HostName:1;
142
    } bits;
143
    BYTE Val;
144
} ValidValues;
145
 
146
static BYTE _DHCPReceive(void);
147
static void _DHCPSend(BYTE messageType);
148
 
149
BYTE DHCPBindCount = 0;
150
 
151
// Uncomment following line if DHCP transactions are to be displayed on
152
// RS-232 - for debug purpose only.
153
//#define DHCP_DEBUG_MODE
154
 
155
#if defined(DHCP_DEBUG_MODE)
156
static USARTPut(BYTE c)
157
{
158
    while( !TXSTA_TRMT);
159
    TXREG = c;
160
}
161
#else
162
 
163
#define USARTPut(a)
164
 
165
#endif
166
 
167
 
168
void DHCPReset(void)
169
{
170
    // Do not reset DHCP if it was previously disabled.
171
    if ( smDHCPState == SM_DHCP_DISABLED )
172
        return;
173
 
174
    if ( DHCPSocket != INVALID_UDP_SOCKET )
175
        UDPClose(DHCPSocket);
176
    DHCPSocket = INVALID_UDP_SOCKET;
177
 
178
    smDHCPState = SM_DHCP_INIT_FIRST_TIME;
179
    DHCPBindCount = 0;
180
 
181
    DHCPState.bits.bIsBound = FALSE;
182
}
183
 
184
/*********************************************************************
185
 * Function:        void DHCPTask(void)
186
 *
187
 * PreCondition:    DHCPInit() is already called AND
188
 *                  IPGetHeader() is called with
189
 *                  IPFrameType == IP_PROT_UDP
190
 *
191
 * Input:           None
192
 *
193
 * Output:          None
194
 *
195
 * Side Effects:    None
196
 *
197
 * Overview:        Fetches pending UDP packet from MAC receive buffer
198
 *                  and dispatches it appropriate UDP socket.
199
 *                  If not UDP socket is matched, UDP packet is
200
 *                  silently discarded.
201
 *
202
 * Note:            Caller must make sure that MAC receive buffer
203
 *                  access pointer is set to begining of UDP packet.
204
 *                  Required steps before calling this function is:
205
 *
206
 *                  If ( MACIsRxReady() )
207
 *                  {
208
 *                      MACGetHeader()
209
 *                      If MACFrameType == IP
210
 *                          IPGetHeader()
211
 *                          if ( IPFrameType == IP_PROT_UDP )
212
 *                              Call DHCPTask()
213
 *                  ...
214
 ********************************************************************/
215
void DHCPTask(void)
216
{
217
    NODE_INFO DHCPServerNode;
218
    static TICK lastTryTick;
219
    BYTE DHCPRecvReturnValue;
220
    TICK tickDiff;
221
 
222
    switch(smDHCPState)
223
    {
224
    case SM_DHCP_INIT_FIRST_TIME:
225
        tempIPAddress.Val = 0x0;
226
//        smDHCPState = SM_DHCP_INIT;           // State automatically changes
227
        /* No break */
228
 
229
    case SM_DHCP_INIT:
230
        DHCPServerNode.MACAddr.v[0] = 0xff;
231
        DHCPServerNode.MACAddr.v[1] = 0xff;
232
        DHCPServerNode.MACAddr.v[2] = 0xff;
233
        DHCPServerNode.MACAddr.v[3] = 0xff;
234
        DHCPServerNode.MACAddr.v[4] = 0xff;
235
        DHCPServerNode.MACAddr.v[5] = 0xff;
236
        DHCPServerNode.IPAddr.Val = 0xffffffff;
237
        DHCPSocket = UDPOpen(DHCP_CLIENT_PORT,
238
                             &DHCPServerNode,
239
                             DHCP_SERVER_PORT);
240
        lastTryTick = TickGet();
241
        smDHCPState = SM_DHCP_RESET_WAIT;
242
        /* No break */
243
 
244
    case SM_DHCP_RESET_WAIT:
245
        if ( TickGetDiff(TickGet(), lastTryTick) >= (TICK_SECOND/(TICK)5) )
246
            smDHCPState = SM_DHCP_BROADCAST;
247
        break;
248
 
249
    case SM_DHCP_BROADCAST:
250
        // Assume default IP Lease time of 60 seconds.
251
        // This should be minimum possible to make sure that if
252
        // server did not specify lease time, we try again after this minimum time.
253
        DHCPLeaseTime.Val = 60;
254
 
255
        // If we have already obtained some IP address, renew it.
256
        if(DHCPState.bits.bIsBound)
257
        {
258
            smDHCPState = SM_DHCP_REQUEST;
259
        }
260
        else if ( UDPIsPutReady(DHCPSocket) )
261
        {
262
            // To minimize code requirement, user must make sure that
263
            // above call will be successful by making at least one
264
            // UDP socket available.
265
            // Usually this will be the case, given that DHCP will be
266
            // the first one to use UDP socket.
267
            // Also, we will not check for transmitter readiness,
268
            // we assume it to be ready.
269
            _DHCPSend(DHCP_DISCOVER_MESSAGE);
270
            ValidValues.Val = 0x00;
271
 
272
            // DEBUG
273
            USARTPut('\n');
274
            USARTPut('\r');
275
            USARTPut('D');
276
 
277
            lastTryTick = TickGet();
278
            smDHCPState = SM_DHCP_DISCOVER;
279
        }
280
 
281
        break;
282
 
283
 
284
    case SM_DHCP_DISCOVER:
285
        if ( TickGetDiff(TickGet(), lastTryTick) >= DHCP_TIMEOUT )
286
        {
287
            smDHCPState = SM_DHCP_BROADCAST;
288
            //return;
289
        }
290
 
291
        if ( UDPIsGetReady(DHCPSocket) )
292
        {
293
            // DEBUG
294
            USARTPut('R');
295
 
296
            if ( _DHCPReceive() == DHCP_OFFER_MESSAGE )
297
            {
298
                // DEBUG
299
                USARTPut('O');
300
 
301
                smDHCPState = SM_DHCP_REQUEST;
302
            }
303
            else
304
                break;
305
        }
306
        else
307
            break;
308
 
309
 
310
 
311
    case SM_DHCP_REQUEST:
312
        if ( UDPIsPutReady(DHCPSocket) )
313
        {
314
            _DHCPSend(DHCP_REQUEST_MESSAGE);
315
 
316
            lastTryTick = TickGet();
317
            smDHCPState = SM_DHCP_BIND;
318
        }
319
        break;
320
 
321
    case SM_DHCP_BIND:
322
        if ( UDPIsGetReady(DHCPSocket) )
323
        {
324
            DHCPRecvReturnValue = _DHCPReceive();
325
            if ( DHCPRecvReturnValue == DHCP_NAK_MESSAGE )
326
            {
327
                // (RSS) NAK recieved.  DHCP server didn't like our DHCP Request (format wrong/IP address allocated to someone else/outside IP pool)
328
                USARTPut('n');
329
                DHCPReset();                        // Start all over again
330
                return;
331
            }
332
            else if ( DHCPRecvReturnValue == DHCP_ACK_MESSAGE )
333
            {
334
                // DEBUG
335
                USARTPut('B');
336
 
337
                // Once DCHP is successful, release the UDP socket
338
                // This will ensure that UDP layer discards any further DHCP related packets.
339
                UDPClose(DHCPSocket);
340
                DHCPSocket = INVALID_UDP_SOCKET;
341
 
342
                lastTryTick = TickGet();
343
                smDHCPState = SM_DHCP_BOUND;
344
 
345
                if(ValidValues.bits.IPAddress)
346
                    AppConfig.MyIPAddr = tempIPAddress;
347
                if(ValidValues.bits.Mask)
348
                    AppConfig.MyMask = tempMask;
349
                if(ValidValues.bits.Gateway)
350
                    AppConfig.MyGateway = tempGateway;
351
#if defined(STACK_USE_DNS)
352
                if(ValidValues.bits.DNS)
353
                    AppConfig.PrimaryDNSServer = tempDNS;
354
#endif
355
//              if(ValidValues.bits.HostName)
356
//                  memcpy(AppConfig.NetBIOSName, (void*)tempHostName, sizeof(AppConfig.NetBIOSName));
357
 
358
                DHCPState.bits.bIsBound = TRUE;
359
 
360
                DHCPBindCount++;
361
 
362
                return;
363
            }
364
        }
365
        else if ( TickGetDiff(TickGet(), lastTryTick) >= DHCP_TIMEOUT )
366
        {
367
            USARTPut('t');
368
            smDHCPState = SM_DHCP_BROADCAST;
369
        }
370
        break;
371
 
372
    case SM_DHCP_BOUND:
373
        // Keep track of how long we use this IP configuration.
374
        // When lease period expires, renew the configuration.
375
        tickDiff = TickGetDiff(TickGet(), lastTryTick);
376
 
377
        if(tickDiff >= TICK_SECOND)
378
        {
379
            do
380
            {
381
                DHCPLeaseTime.Val--;
382
                tickDiff -= TICK_SECOND;
383
                if(DHCPLeaseTime.Val == 0u)
384
                    smDHCPState = SM_DHCP_INIT;
385
            } while(tickDiff >= TICK_SECOND);
386
            lastTryTick = TickGet() - tickDiff;
387
        }
388
    }
389
}
390
 
391
 
392
 
393
/*********************************************************************
394
        DHCP PACKET FORMAT AS PER RFC 1541
395
 
396
 
397
 
398
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
399
   |     op (1)    |   htype (1)   |   hlen (1)    |   hops (1)    |
400
   +---------------+---------------+---------------+---------------+
401
   |                            xid (4)                            |
402
   +-------------------------------+-------------------------------+
403
   |           secs (2)            |           flags (2)           |
404
   +-------------------------------+-------------------------------+
405
   |                          ciaddr  (4)                          |
406
   +---------------------------------------------------------------+
407
   |                          yiaddr  (4)                          |
408
   +---------------------------------------------------------------+
409
   |                          siaddr  (4)                          |
410
   +---------------------------------------------------------------+
411
   |                          giaddr  (4)                          |
412
   +---------------------------------------------------------------+
413
   |                                                               |
414
   |                          chaddr  (16)                         |
415
   |                                                               |
416
   |                                                               |
417
   +---------------------------------------------------------------+
418
   |                                                               |
419
   |                          sname   (64)                         |
420
   +---------------------------------------------------------------+
421
   |                                                               |
422
   |                          file    (128)                        |
423
   +---------------------------------------------------------------+
424
   |                                                               |
425
   |                          options (312)                        |
426
   +---------------------------------------------------------------+
427
 
428
 ********************************************************************/
429
static BYTE _DHCPReceive(void)
430
{
431
    BYTE v;
432
    BYTE i, j;
433
    BYTE type;
434
    BOOL lbDone;
435
    DWORD_VAL tempServerID;
436
 
437
 
438
    // Assume unknown message until proven otherwise.
439
    type = DHCP_UNKNOWN_MESSAGE;
440
 
441
    UDPGet(&v);                             // op
442
 
443
    // Make sure this is BOOT_REPLY.
444
    if ( v == BOOT_REPLY )
445
    {
446
        // Discard htype, hlen, hops, xid, secs, flags, ciaddr.
447
        for ( i = 0; i < 15u; i++ )
448
            UDPGet(&v);
449
 
450
        // Check to see if this is the first offer
451
        if(DHCPState.bits.bOfferReceived)
452
        {
453
            // Discard offered IP address, we already have an offer
454
            for ( i = 0; i < 4u; i++ )
455
                UDPGet(&v);
456
        }
457
        else
458
        {
459
            // Save offered IP address until we know for sure that we have it.
460
            UDPGet(&tempIPAddress.v[0]);
461
            UDPGet(&tempIPAddress.v[1]);
462
            UDPGet(&tempIPAddress.v[2]);
463
            UDPGet(&tempIPAddress.v[3]);
464
            ValidValues.bits.IPAddress = 1;
465
        }
466
 
467
        // Ignore siaddr, giaddr
468
        for ( i = 0; i < 8u; i++ )
469
            UDPGet(&v);
470
 
471
        // Check to see if chaddr (Client Hardware Address) belongs to us.
472
        for ( i = 0; i < 6u; i++ )
473
        {
474
            UDPGet(&v);
475
            if ( v != AppConfig.MyMACAddr.v[i])
476
                goto UDPInvalid;
477
        }
478
 
479
 
480
        // Ignore part of chaddr, sname, file, magic cookie.
481
        for ( i = 0; i < 206u; i++ )
482
            UDPGet(&v);
483
 
484
        lbDone = FALSE;
485
        do
486
        {
487
            // Get the Option number
488
            // Break out eventually in case if this is a malformed 
489
            // DHCP message, ie: missing DHCP_END_OPTION marker
490
            if(!UDPGet(&v))
491
            {
492
                lbDone = TRUE;
493
                break;
494
            }
495
 
496
            switch(v)
497
            {
498
            case DHCP_MESSAGE_TYPE:
499
                UDPGet(&v);                         // Skip len
500
                // Len must be 1.
501
                if ( v == 1u )
502
                {
503
                    UDPGet(&type);                  // Get type
504
 
505
                    // Throw away the packet if we know we don't need it (ie: another offer when we already have one)
506
                    if(DHCPState.bits.bOfferReceived && (type == DHCP_OFFER_MESSAGE))
507
                    {
508
                        goto UDPInvalid;
509
                    }
510
                }
511
                else
512
                    goto UDPInvalid;
513
                break;
514
 
515
            case DHCP_SUBNET_MASK:
516
                UDPGet(&v);                     // Skip len
517
                // Len must be 4.
518
                if ( v == 4u )
519
                {
520
                    // Check to see if this is the first offer
521
                    if(DHCPState.bits.bOfferReceived)
522
                    {
523
                        // Discard offered IP mask, we already have an offer
524
                        for ( i = 0; i < 4u; i++ )
525
                            UDPGet(&v);
526
                    }
527
                    else
528
                    {
529
                        UDPGet(&tempMask.v[0]);
530
                        UDPGet(&tempMask.v[1]);
531
                        UDPGet(&tempMask.v[2]);
532
                        UDPGet(&tempMask.v[3]);
533
                        ValidValues.bits.Mask = 1;
534
                    }
535
                }
536
                else
537
                    goto UDPInvalid;
538
                break;
539
 
540
            case DHCP_ROUTER:
541
                UDPGet(&j);
542
                // Len must be >= 4.
543
                if ( j >= 4u )
544
                {
545
                    // Check to see if this is the first offer
546
                    if(DHCPState.bits.bOfferReceived)
547
                    {
548
                        // Discard offered Gateway address, we already have an offer
549
                        for ( i = 0; i < 4u; i++ )
550
                            UDPGet(&v);
551
                    }
552
                    else
553
                    {
554
                        UDPGet(&tempGateway.v[0]);
555
                        UDPGet(&tempGateway.v[1]);
556
                        UDPGet(&tempGateway.v[2]);
557
                        UDPGet(&tempGateway.v[3]);
558
                        ValidValues.bits.Gateway = 1;
559
                    }
560
                }
561
                else
562
                    goto UDPInvalid;
563
 
564
                // Discard any other router addresses.
565
                j -= 4;
566
                while(j--)
567
                    UDPGet(&v);
568
                break;
569
 
570
#if defined(STACK_USE_DNS)
571
            case DHCP_DNS:
572
                UDPGet(&j);
573
                // Len must be >= 4.
574
                if ( j >= 4u )
575
                {
576
                    // Check to see if this is the first offer
577
                    if(DHCPState.bits.bOfferReceived)
578
                    {
579
                        // Discard offered DNS server address, we already have an offer
580
                        for ( i = 0; i < 4u; i++ )
581
                            UDPGet(&v);
582
                    }
583
                    else
584
                    {
585
                        UDPGet(&tempDNS.v[0]);
586
                        UDPGet(&tempDNS.v[1]);
587
                        UDPGet(&tempDNS.v[2]);
588
                        UDPGet(&tempDNS.v[3]);
589
                        ValidValues.bits.DNS = 1;
590
                    }
591
                }
592
                else
593
                    goto UDPInvalid;
594
 
595
                // Discard any other DNS server addresses
596
                j -= 4;
597
                while(j--)
598
                    UDPGet(&v);
599
                break;
600
#endif
601
 
602
//            case DHCP_HOST_NAME:
603
//                UDPGet(&j);
604
//                // Len must be >= 4.
605
//                if(j < 1u)
606
//                  goto UDPInvalid;
607
//
608
//              // Check to see if this is the first offer
609
//              if(DHCPState.bits.bOfferReceived)
610
//              {
611
//                  // Discard offered host name, we already have an offer
612
//                  while(j--)
613
//                      UDPGet(&v);
614
//              }
615
//              else
616
//              {
617
//                  for(i = 0; j, i < sizeof(tempHostName); i++, j--)
618
//                  {
619
//                      UDPGet(&tempHostName[i]);
620
//                  }
621
//                  while(j--)
622
//                  {
623
//                      UDPGet(&v);
624
//                  }
625
//                  ValidValues.bits.HostName = 1;
626
//              }
627
//
628
//                break;
629
 
630
            case DHCP_SERVER_IDENTIFIER:
631
                UDPGet(&v);                         // Get len
632
                // Len must be 4.
633
                if ( v == 4u )
634
                {
635
                    UDPGet(&tempServerID.v[3]);   // Get the id
636
                    UDPGet(&tempServerID.v[2]);
637
                    UDPGet(&tempServerID.v[1]);
638
                    UDPGet(&tempServerID.v[0]);
639
                }
640
                else
641
                    goto UDPInvalid;
642
                break;
643
 
644
            case DHCP_END_OPTION:
645
                lbDone = TRUE;
646
                break;
647
 
648
            case DHCP_IP_LEASE_TIME:
649
                UDPGet(&v);                         // Get len
650
                // Len must be 4.
651
                if ( v == 4u )
652
                {
653
                    // Check to see if this is the first offer
654
                    if(DHCPState.bits.bOfferReceived)
655
                    {
656
                        // Discard offered lease time, we already have an offer
657
                        for ( i = 0; i < 4u; i++ )
658
                            UDPGet(&v);
659
                    }
660
                    else
661
                    {
662
                        UDPGet(&DHCPLeaseTime.v[3]);
663
                        UDPGet(&DHCPLeaseTime.v[2]);
664
                        UDPGet(&DHCPLeaseTime.v[1]);
665
                        UDPGet(&DHCPLeaseTime.v[0]);
666
 
667
                        // Due to possible timing delays, consider actual lease
668
                        // time less by half hour.
669
                        if ( DHCPLeaseTime.Val > HALF_HOUR )
670
                            DHCPLeaseTime.Val = DHCPLeaseTime.Val - HALF_HOUR;
671
                    }
672
                }
673
                else
674
                    goto UDPInvalid;
675
                break;
676
 
677
            default:
678
                // Ignore all unsupport tags.
679
                UDPGet(&j);                     // Get option len
680
                while( j-- )                    // Ignore option values
681
                    UDPGet(&v);
682
            }
683
        } while( !lbDone );
684
    }
685
 
686
    // If this is an OFFER message, remember current server id.
687
    if ( type == DHCP_OFFER_MESSAGE )
688
    {
689
        DHCPServerID.Val = tempServerID.Val;
690
        DHCPState.bits.bOfferReceived = TRUE;
691
    }
692
    else
693
    {
694
        // For other types of messages, make sure that received
695
        // server id matches with our previous one.
696
        if ( DHCPServerID.Val != tempServerID.Val )
697
            type = DHCP_UNKNOWN_MESSAGE;
698
    }
699
 
700
    UDPDiscard();                             // We are done with this packet
701
    return type;
702
 
703
UDPInvalid:
704
    UDPDiscard();
705
    return DHCP_UNKNOWN_MESSAGE;
706
 
707
}
708
 
709
 
710
 
711
 
712
 
713
static void _DHCPSend(BYTE messageType)
714
{
715
    BYTE i;
716
 
717
 
718
    UDPPut(BOOT_REQUEST);                       // op
719
    UDPPut(HW_TYPE);                            // htype
720
    UDPPut(LEN_OF_HW_TYPE);                     // hlen
721
    UDPPut(0);                                  // hops
722
    UDPPut(0x12);                               // xid[0]
723
    UDPPut(0x23);                               // xid[1]
724
    UDPPut(0x34);                               // xid[2]
725
    UDPPut(0x56);                               // xid[3]
726
    UDPPut(0);                                  // secs[0]
727
    UDPPut(0);                                  // secs[1]
728
    UDPPut(0x80);                               // flags[0] with BF set
729
    UDPPut(0);                                  // flags[1]
730
 
731
    // If this is DHCP REQUEST message, use previously allocated IP address.
732
#if 0
733
    if ( messageType == DHCP_REQUEST_MESSAGE )
734
    {
735
        UDPPut(tempIPAddress.v[0]);
736
        UDPPut(tempIPAddress.v[1]);
737
        UDPPut(tempIPAddress.v[2]);
738
        UDPPut(tempIPAddress.v[3]);
739
    }
740
    else
741
#endif
742
    {
743
        UDPPut(0x00);
744
        UDPPut(0x00);
745
        UDPPut(0x00);
746
        UDPPut(0x00);
747
    }
748
 
749
    // Set yiaddr, siaddr, giaddr as zeros,
750
    for ( i = 0; i < 12u; i++ )
751
        UDPPut(0x00);
752
 
753
    // Load chaddr - Client hardware address.
754
    UDPPut(AppConfig.MyMACAddr.v[0]);
755
    UDPPut(AppConfig.MyMACAddr.v[1]);
756
    UDPPut(AppConfig.MyMACAddr.v[2]);
757
    UDPPut(AppConfig.MyMACAddr.v[3]);
758
    UDPPut(AppConfig.MyMACAddr.v[4]);
759
    UDPPut(AppConfig.MyMACAddr.v[5]);
760
 
761
    // Set chaddr[6..15], sname and file as zeros.
762
    for ( i = 0; i < 202u; i++ )
763
        UDPPut(0);
764
 
765
    // Load magic cookie as per RFC 1533.
766
    UDPPut(99);
767
    UDPPut(130);
768
    UDPPut(83);
769
    UDPPut(99);
770
 
771
    // Load message type.
772
    UDPPut(DHCP_MESSAGE_TYPE);
773
    UDPPut(DHCP_MESSAGE_TYPE_LEN);
774
    UDPPut(messageType);
775
 
776
    if(messageType == DHCP_DISCOVER_MESSAGE)
777
    {
778
        // Reset offered flag so we know to act upon the next valid offer
779
        DHCPState.bits.bOfferReceived = FALSE;
780
    }
781
 
782
 
783
    if ( messageType != DHCP_DISCOVER_MESSAGE && tempIPAddress.Val != 0x0000u )
784
    {
785
         // DHCP REQUEST message may include server identifier,
786
         // to identify the server we are talking to.
787
         // DHCP ACK may include it too.  To simplify logic,
788
         // we will include server identifier in DHCP ACK message too.
789
         // _DHCPReceive() would populate "serverID" when it
790
         // receives DHCP OFFER message. We will simply use that
791
         // when we are replying to server.
792
         // If this is a renwal request, do not include server id.
793
         UDPPut(DHCP_SERVER_IDENTIFIER);
794
         UDPPut(DHCP_SERVER_IDENTIFIER_LEN);
795
         UDPPut(DHCPServerID.v[3]);
796
         UDPPut(DHCPServerID.v[2]);
797
         UDPPut(DHCPServerID.v[1]);
798
         UDPPut(DHCPServerID.v[0]);
799
     }
800
 
801
    // Load our interested parameters
802
    // This is hardcoded list.  If any new parameters are desired,
803
    // new lines must be added here.
804
    UDPPut(DHCP_PARAM_REQUEST_LIST);
805
    UDPPut(DHCP_PARAM_REQUEST_LIST_LEN);
806
    UDPPut(DHCP_SUBNET_MASK);
807
    UDPPut(DHCP_ROUTER);
808
    UDPPut(DHCP_DNS);
809
    UDPPut(DHCP_HOST_NAME);
810
 
811
     // Add requested IP address to DHCP Request Message
812
    if ( messageType == DHCP_REQUEST_MESSAGE )
813
    {
814
        UDPPut(DHCP_PARAM_REQUEST_IP_ADDRESS);
815
        UDPPut(DHCP_PARAM_REQUEST_IP_ADDRESS_LEN);
816
 
817
        UDPPut(tempIPAddress.v[0]);
818
        UDPPut(tempIPAddress.v[1]);
819
        UDPPut(tempIPAddress.v[2]);
820
        UDPPut(tempIPAddress.v[3]);
821
    }
822
 
823
    // Add any new paramter request here.
824
 
825
    // End of Options.
826
    UDPPut(DHCP_END_OPTION);
827
 
828
    UDPFlush();
829
}
830
 
831
 
832
#endif  //#if defined(STACK_USE_DHCP)