OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [bootloaders/] [orpmon/] [services/] [bootp.c] - Blame information for rev 197

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 marcus.erl
/*
2
 *      Based on LiMon - BOOTP.
3
 *
4
 *      Copyright 1994, 1995, 2000 Neil Russell.
5
 *      (See License)
6
 *      Copyright 2000 Roland Borde
7
 *      Copyright 2000 Paolo Scaffardi
8
 */
9
 
10 140 julius
#if 1
11 2 marcus.erl
#define DEBUG           1       /* general debug */
12
#define DEBUG_BOOTP_EXT 1       /* Debug received vendor fields */
13
#endif
14
 
15
#ifdef DEBUG_BOOTP_EXT
16
#define debug_ext(fmt,args...)  printf (fmt ,##args)
17
#else
18
#define debug_ext(fmt,args...)
19
#endif
20
 
21
#include "common.h"
22
#include "net.h"
23
#include "bootp.h"
24
#include "tftp.h"
25
#include "arp.h"
26
 
27
#define BOOTP_VENDOR_MAGIC      0x63825363      /* RFC1048 Magic Cookie         */
28
 
29
#if (CONFIG_COMMANDS & CFG_CMD_NET)
30
 
31
#define TIMEOUT         5               /* Seconds before trying BOOTP again    */
32
#define TIMEOUT_COUNT   1               /* # of timeouts before giving up       */
33
 
34
#define PORT_BOOTPS     67              /* BOOTP server UDP port                */
35
#define PORT_BOOTPC     68              /* BOOTP client UDP port                */
36
 
37
#ifndef CONFIG_DHCP_MIN_EXT_LEN         /* minimal length of extension list     */
38
#define CONFIG_DHCP_MIN_EXT_LEN 64
39
#endif
40
 
41
ulong           BootpID;
42
int             BootpTry;
43
#ifdef CONFIG_BOOTP_RANDOM_DELAY
44
ulong           seed1, seed2;
45
#endif
46
 
47
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
48
dhcp_state_t dhcp_state = INIT;
49
unsigned int dhcp_leasetime = 0;
50
static void DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len);
51
 
52
/* For Debug */
53
char *dhcpmsg2str(int type)
54
{
55
        switch (type) {
56
        case 1: return "DHCPDISCOVER"; break;
57
        case 2: return "DHCPOFFER"; break;
58
        case 3: return "DHCPREQUEST"; break;
59
        case 4: return "DHCPDECLINE"; break;
60
        case 5: return "DHCPACK"; break;
61
        case 6: return "DHCPNACK"; break;
62
        case 7: return "DHCPRELEASE"; break;
63
        default: return "UNKNOWN/INVALID MSG TYPE"; break;
64
        }
65
}
66
 
67
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
68
extern u8 *dhcp_vendorex_prep (u8 *e); /*rtn new e after add own opts. */
69
extern u8 *dhcp_vendorex_proc (u8 *e); /*rtn next e if mine,else NULL  */
70
#endif
71
 
72
#endif  /* CFG_CMD_DHCP */
73
 
74
static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len)
75
{
76
        Bootp_t *bp = (Bootp_t *) pkt;
77
        int retval = 0;
78
 
79
        if (dest != PORT_BOOTPC || src != PORT_BOOTPS)
80
                retval = -1;
81
        if (len < sizeof (Bootp_t) - OPT_SIZE)
82
                retval = -2;
83
        if (bp->bp_op != OP_BOOTREQUEST &&
84
            bp->bp_op != OP_BOOTREPLY &&
85
            bp->bp_op != DHCP_OFFER &&
86
            bp->bp_op != DHCP_ACK &&
87
            bp->bp_op != DHCP_NAK ) {
88
                retval = -3;
89
        }
90
        if (bp->bp_htype != HWT_ETHER)
91
                retval = -4;
92
        if (bp->bp_hlen != HWL_ETHER)
93
                retval = -5;
94
        if (bp->bp_id != BootpID)
95
                retval = -6;
96
 
97
        debug ("Filtering pkt = %d\n", retval);
98
 
99
        return retval;
100
}
101
 
102
/*
103
 * Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet
104
 */
105
void BootpCopyNetParams(Bootp_t *bp)
106
{
107
        NetOurIP = bp->bp_yiaddr;
108
        NetServerIP = bp->bp_siaddr;
109
        NetCopyEther(NetServerEther, ((Ethernet_t *)NetRxPkt)->et_src);
110
        copy_filename (BootFile, bp->bp_file, sizeof(BootFile));
111
 
112
        debug ("Bootfile: %s\n", BootFile);
113
 
114
        /* Propagate to environment:
115
         * don't delete exising entry when BOOTP / DHCP reply does
116
         * not contain a new value
117
         */
118
        if (*BootFile) {
119
                setenv ("bootfile", BootFile);
120
        }
121
}
122
 
123
static int truncate_sz (const char *name, int maxlen, int curlen)
124
{
125
        if (curlen >= maxlen) {
126
                printf("*** WARNING: %s is too long (%d - max: %d) - truncated\n",
127
                        name, curlen, maxlen);
128
                curlen = maxlen - 1;
129
        }
130
        return (curlen);
131
}
132
 
133
#if !(CONFIG_COMMANDS & CFG_CMD_DHCP)
134
 
135
static void BootpVendorFieldProcess(u8 *ext)
136
{
137
    int size = *(ext+1) ;
138
 
139
    debug_ext ("[BOOTP] Processing extension %d... (%d bytes)\n", *ext, *(ext+1));
140
 
141
    NetBootFileSize = 0;
142
 
143
    switch (*ext) {
144
    /* Fixed length fields */
145
        case 1:         /* Subnet mask                                  */
146
                if (NetOurSubnetMask == 0)
147
                    memcpy(&NetOurSubnetMask, ext+2, 4);
148
                break;
149
        case 2:         /* Time offset - Not yet supported              */
150
                break;
151
    /* Variable length fields */
152
        case 3:         /* Gateways list                                */
153
                if (NetOurGatewayIP == 0) {
154
                    memcpy(&NetOurGatewayIP, ext+2, 4);
155
                }
156
                break;
157
        case 4:         /* Time server - Not yet supported              */
158
                break;
159
        case 5:         /* IEN-116 name server - Not yet supported      */
160
                break;
161
        case 6:
162
                if (NetOurDNSIP == 0) {
163
                    memcpy(&NetOurDNSIP, ext+2, 4);
164
                }
165
                break;
166
        case 7:         /* Log server - Not yet supported               */
167
                break;
168
        case 8:         /* Cookie/Quote server - Not yet supported      */
169
                break;
170
        case 9:         /* LPR server - Not yet supported               */
171
                break;
172
        case 10:        /* Impress server - Not yet supported           */
173
                break;
174
        case 11:        /* RPL server - Not yet supported               */
175
                break;
176
        case 12:        /* Host name                                    */
177
                if (NetOurHostName[0] == 0) {
178
                    size = truncate_sz("Host Name", sizeof(NetOurHostName), size);
179
                    memcpy(&NetOurHostName, ext+2, size);
180
                    NetOurHostName[size] = 0 ;
181
                }
182
                break;
183
        case 13:        /* Boot file size                               */
184
                memcpy(&NetBootFileSize, ext+2, size);
185
                break;
186
        case 14:        /* Merit dump file - Not yet supported          */
187
                break;
188
        case 15:        /* Domain name - Not yet supported              */
189
                break;
190
        case 16:        /* Swap server - Not yet supported              */
191
                break;
192
        case 17:        /* Root path                                    */
193
                if (NetOurRootPath[0] == 0) {
194
                    size = truncate_sz("Root Path", sizeof(NetOurRootPath), size);
195
                    memcpy(&NetOurRootPath, ext+2, size);
196
                    NetOurRootPath[size] = 0 ;
197
                }
198
                break;
199
        case 18:        /* Extension path - Not yet supported           */
200
                /*
201
                 * This can be used to send the informations of the
202
                 * vendor area in another file that the client can
203
                 * access via TFTP.
204
                 */
205
                break;
206
    /* IP host layer fields */
207
        case 40:        /* NIS Domain name                              */
208
                if (NetOurNISDomain[0] == 0) {
209
                    size = truncate_sz ("NIS Domain Name",
210
                                        sizeof(NetOurNISDomain),
211
                                        size);
212
                    memcpy(&NetOurNISDomain, ext+2, size);
213
                    NetOurNISDomain[size] = 0 ;
214
                }
215
                break;
216
    /* Application layer fields */
217
        case 43:        /* Vendor specific info - Not yet supported     */
218
                /*
219
                 * Binary informations to exchange specific
220
                 * product information.
221
                 */
222
                break;
223
    /* Reserved (custom) fields (128..254) */
224
    }
225
}
226
 
227
static void BootpVendorProcess(u8 *ext, int size)
228
{
229
    u8 *end = ext + size ;
230
 
231
    debug_ext ("[BOOTP] Checking extension (%d bytes)...\n", size);
232
 
233
    while ((ext < end) && (*ext != 0xff)) {
234
        if (*ext == 0) {
235
            ext ++ ;
236
        } else {
237
                u8 *opt = ext ;
238
                ext += ext[1] + 2 ;
239
                if (ext <= end)
240
                    BootpVendorFieldProcess (opt) ;
241
        }
242
    }
243
 
244
#ifdef DEBUG_BOOTP_EXT
245
    printf("[BOOTP] Received fields: \n");
246
    if (NetOurSubnetMask) {
247
        puts ("NetOurSubnetMask : ");
248
        print_IPaddr (NetOurSubnetMask);
249
        putc('\n');
250
    }
251
 
252
    if (NetOurGatewayIP) {
253
        puts ("NetOurGatewayIP  : ");
254
        print_IPaddr (NetOurGatewayIP);
255
        putc('\n');
256
    }
257
 
258
    if (NetBootFileSize) {
259
        printf("NetBootFileSize : %d\n", NetBootFileSize);
260
    }
261
 
262
    if (NetOurHostName[0]) {
263
        printf("NetOurHostName  : %s\n", NetOurHostName);
264
    }
265
 
266
    if (NetOurRootPath[0]) {
267
        printf("NetOurRootPath  : %s\n", NetOurRootPath);
268
    }
269
 
270
    if (NetOurNISDomain[0]) {
271
        printf("NetOurNISDomain : %s\n", NetOurNISDomain);
272
    }
273
#endif  /* DEBUG_BOOTP_EXT */
274
}
275
 
276
/*
277
 *      Handle a BOOTP received packet.
278
 */
279
static void
280
BootpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
281
{
282
        Bootp_t *bp;
283
        char    *s;
284
 
285
        debug ("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%d)\n",
286
                src, dest, len, sizeof (Bootp_t));
287
 
288
        bp = (Bootp_t *)pkt;
289
 
290
        if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
291
                return;
292
 
293
        /*
294
         *      Got a good BOOTP reply.  Copy the data into our variables.
295
         */
296
#ifdef CONFIG_STATUS_LED
297
        status_led_set (STATUS_LED_BOOT, STATUS_LED_OFF);
298
#endif
299
 
300
        BootpCopyNetParams(bp);         /* Store net parameters from reply */
301
 
302
        /* Retrieve extended informations (we must parse the vendor area) */
303
        if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC)
304
            BootpVendorProcess(&bp->bp_vend[4], len);
305
 
306
        NetSetTimeout(0, (thand_f *)0);
307
 
308
        debug ("Got good BOOTP\n");
309
 
310
        if (((s = getenv("autoload")) != NULL) && (*s == 'n')) {
311
                /*
312
                 * Just use BOOTP to configure system;
313
                 * Do not use TFTP to load the bootfile.
314
                 */
315
                NetState = NETLOOP_SUCCESS;
316
                return;
317
        }
318
 
319
        /* Send ARP request to get TFTP server ethernet address.
320
         * This automagically starts TFTP, too.
321
         */
322
        ArpRequest();
323
}
324
#endif  /* !CFG_CMD_DHCP */
325
 
326
/*
327
 *      Timeout on BOOTP/DHCP request.
328
 */
329
static void
330
BootpTimeout(void)
331
{
332
        if (BootpTry >= TIMEOUT_COUNT) {
333
                puts ("\nRetry count exceeded; starting again\n");
334
                NetStartAgain ();
335
        } else {
336
                NetSetTimeout (TIMEOUT * CFG_HZ, BootpTimeout);
337
                BootpRequest ();
338
        }
339
}
340
 
341
/*
342
 *      Initialize BOOTP extension fields in the request.
343
 */
344
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
345
static int DhcpExtended(u8 *e, int message_type, IPaddr_t ServerID, IPaddr_t RequestedIP)
346
{
347
    u8 *start = e ;
348
    u8 *cnt;
349
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
350
    u8 *x;
351
#endif
352
 
353
    *e++ =  99;         /* RFC1048 Magic Cookie */
354
    *e++ = 130;
355
    *e++ =  83;
356
    *e++ =  99;
357
 
358
    *e++ = 53;          /* DHCP Message Type */
359
    *e++ = 1;
360
    *e++ = message_type;
361
 
362
    *e++ = 57;          /* Maximum DHCP Message Size */
363
    *e++ = 2;
364
    *e++ = (576-312+OPT_SIZE) >> 8;
365
    *e++ = (576-312+OPT_SIZE) & 0xff;
366
 
367
    if ( ServerID ) {
368
            *e++ = 54;  /* ServerID */
369
            *e++ = 4;
370
            *e++ = ServerID >> 24;
371
            *e++ = ServerID >> 16;
372
            *e++ = ServerID >> 8;
373
            *e++ = ServerID & 0xff;
374
    }
375
 
376
    if ( RequestedIP ) {
377
            *e++ = 50;  /* Requested IP */
378
            *e++ = 4;
379
            *e++ = RequestedIP >> 24;
380
            *e++ = RequestedIP >> 16;
381
            *e++ = RequestedIP >> 8;
382
            *e++ = RequestedIP & 0xff;
383
    }
384
 
385
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
386
    if ((x = dhcp_vendorex_prep (e)))
387
        return x - start ;
388
#endif
389
 
390
    *e++ = 55;          /* Parameter Request List */
391
    cnt  = e++;         /* Pointer to count of requested items */
392
    *cnt = 0;
393
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SUBNETMASK)
394
    *e++ = 1;           /* Subnet Mask */
395
    *cnt += 1;
396
#endif
397
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_GATEWAY)
398
    *e++ = 3;           /* Router Option */
399
    *cnt += 1;
400
#endif
401
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS)
402
    *e++ = 6;           /* DNS Server(s) */
403
    *cnt += 1;
404
#endif
405
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_HOSTNAME)
406
    *e++ = 12;          /* Hostname */
407
    *cnt += 1;
408
#endif
409
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTFILESIZE)
410
    *e++ = 13;          /* Boot File Size */
411
    *cnt += 1;
412
#endif
413
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTPATH)
414
    *e++ = 17;          /* Boot path */
415
    *cnt += 1;
416
#endif
417
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NISDOMAIN)
418
    *e++ = 40;          /* NIS Domain name request */
419
    *cnt += 1;
420
#endif
421
    *e++ = 255;         /* End of the list */
422
 
423
    /* Pad to minimal length */
424
#ifdef  CONFIG_DHCP_MIN_EXT_LEN
425
    while ((e - start) <= CONFIG_DHCP_MIN_EXT_LEN)
426
        *e++ = 0;
427
#endif
428
 
429
    return e - start ;
430
}
431
 
432
#else   /* CFG_CMD_DHCP */
433
/*
434
 *      Warning: no field size check - change CONFIG_BOOTP_MASK at your own risk!
435
 */
436
static int BootpExtended (u8 *e)
437
{
438
    u8 *start = e ;
439
 
440
    *e++ =  99;         /* RFC1048 Magic Cookie */
441
    *e++ = 130;
442
    *e++ =  83;
443
    *e++ =  99;
444
 
445
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
446
    *e++ = 53;          /* DHCP Message Type */
447
    *e++ = 1;
448
    *e++ = DHCP_DISCOVER;
449
 
450
    *e++ = 57;          /* Maximum DHCP Message Size */
451
    *e++ = 2;
452
    *e++ = (576-312+OPT_SIZE) >> 16;
453
    *e++ = (576-312+OPT_SIZE) & 0xff;
454
#endif  /* CFG_CMD_DHCP */
455
 
456
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SUBNETMASK)
457
    *e++ =  1;          /* Subnet mask request */
458
    *e++ =  4;
459
     e  +=  4;
460
#endif
461
 
462
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_GATEWAY)
463
    *e++ =  3;          /* Default gateway request */
464
    *e++ =  4;
465
     e  +=  4;
466
#endif
467
 
468
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS)
469
    *e++ =  6;          /* Domain Name Server */
470
    *e++ =  4;
471
     e  +=  4;
472
#endif
473
 
474
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_HOSTNAME)
475
    *e++ = 12;          /* Host name request */
476
    *e++ = 32;
477
     e  += 32;
478
#endif
479
 
480
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTFILESIZE)
481
    *e++ = 13;          /* Boot file size */
482
    *e++ =  2;
483
     e  +=  2;
484
#endif
485
 
486
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTPATH)
487
    *e++ = 17;          /* Boot path */
488
    *e++ = 32;
489
     e  += 32;
490
#endif
491
 
492
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NISDOMAIN)
493
    *e++ = 40;          /* NIS Domain name request */
494
    *e++ = 32;
495
     e  += 32;
496
#endif
497
 
498
    *e++ = 255;         /* End of the list */
499
 
500
    return e - start ;
501
}
502
#endif  /* CFG_CMD_DHCP */
503
 
504
void
505
BootpRequest (void)
506
{
507
        volatile uchar *pkt, *iphdr;
508
        Bootp_t *bp;
509
        int ext_len, pktlen, iplen;
510
 
511
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
512
        dhcp_state = INIT;
513
#endif
514
 
515
#ifdef CONFIG_BOOTP_RANDOM_DELAY                /* Random BOOTP delay */
516
        unsigned char bi_enetaddr[6];
517
        int   reg;
518
        char  *e,*s;
519
        uchar tmp[64];
520
        ulong tst1, tst2, sum, m_mask, m_value = 0;
521
 
522
        if (BootpTry ==0) {
523
                /* get our mac */
524
                reg = getenv_r ("ethaddr", tmp, sizeof(tmp));
525
                s = (reg > 0) ? tmp : NULL;
526
 
527
                for (reg=0; reg<6; ++reg) {
528
                        bi_enetaddr[reg] = s ? simple_strtoul(s, &e, 16) : 0;
529
                        if (s) {
530
                                s = (*e) ? e+1 : e;
531
                        }
532
                }
533
#ifdef DEBUG
534
                printf("BootpRequest => Our Mac: ");
535
                for (reg=0; reg<6; reg++) {
536
                        printf ("%x%c",
537
                                bi_enetaddr[reg],
538
                                reg==5 ? '\n' : ':');
539
                }
540
#endif /* DEBUG */
541
 
542
                /* Mac-Manipulation 2 get seed1 */
543
                tst1=0;
544
                tst2=0;
545
                for (reg=2; reg<6; reg++) {
546
                        tst1 = tst1 << 8;
547
                        tst1 = tst1 | bi_enetaddr[reg];
548
                }
549
                for (reg=0; reg<2; reg++) {
550
                        tst2 = tst2 | bi_enetaddr[reg];
551
                        tst2 = tst2 << 8;
552
                }
553
 
554
                seed1 = tst1^tst2;
555
 
556
                /* Mirror seed1*/
557
                m_mask=0x1;
558
                for (reg=1;reg<=32;reg++) {
559
                        m_value |= (m_mask & seed1);
560
                        seed1 = seed1 >> 1;
561
                        m_value = m_value << 1;
562
                }
563
                seed1 = m_value;
564
                seed2 = 0xB78D0945;
565
        }
566
 
567
        /* Random Number Generator */
568
 
569
        for (reg=0;reg<=0;reg++) {
570
                sum = seed1 + seed2;
571
                if (sum < seed1 || sum < seed2)
572
                        sum++;
573
                seed2 = seed1;
574
                seed1 = sum;
575
 
576
                if (BootpTry<=2) {      /* Start with max 1024 * 1ms */
577
                        sum = sum >> (22-BootpTry);
578
                } else {                /*After 3rd BOOTP request max 8192 * 1ms */
579
                        sum = sum >> 19;
580
                }
581
        }
582
 
583
        printf ("Random delay: %ld ms...\n", sum);
584
        for (reg=0; reg <sum; reg++) {
585
                udelay(1000); /*Wait 1ms*/
586
        }
587
#endif  /* CONFIG_BOOTP_RANDOM_DELAY */
588
 
589
        printf("BOOTP broadcast %d\n", ++BootpTry);
590
        pkt = NetTxPacket;
591
        memset ((void*)pkt, 0, PKTSIZE);
592
 
593
        NetSetEther(pkt, NetBcastAddr, PROT_IP);
594
        pkt += ETHER_HDR_SIZE;
595
 
596
        /*
597
         * Next line results in incorrect packet size being transmitted, resulting
598
         * in errors in some DHCP servers, reporting missing bytes.  Size must be
599
         * set in packet header after extension length has been determined.
600
         * C. Hallinan, DS4.COM, Inc.
601
         */
602
        /* NetSetIP(pkt, 0xffffffffL, PORT_BOOTPS, PORT_BOOTPC, sizeof (Bootp_t)); */
603
        iphdr = pkt;    /* We need this later for NetSetIP() */
604
        pkt += IP_HDR_SIZE;
605
 
606
        bp = (Bootp_t *)pkt;
607
        bp->bp_op = OP_BOOTREQUEST;
608
        bp->bp_htype = HWT_ETHER;
609
        bp->bp_hlen = HWL_ETHER;
610
        bp->bp_hops = 0;
611
        bp->bp_secs = SWAP16( get_timer(0) / CFG_HZ);
612
        bp->bp_ciaddr = 0;
613
        bp->bp_yiaddr = 0;
614
        bp->bp_siaddr = 0;
615
        bp->bp_giaddr = 0;
616
        NetCopyEther(bp->bp_chaddr, NetOurEther);
617
        copy_filename (bp->bp_file, BootFile, sizeof(bp->bp_file));
618
 
619
        /* Request additional information from the BOOTP/DHCP server */
620
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
621
        ext_len = DhcpExtended(bp->bp_vend, DHCP_DISCOVER, 0, 0);
622
#else
623
        ext_len = BootpExtended(bp->bp_vend);
624
#endif  /* CFG_CMD_DHCP */
625
 
626
        /*
627
         *      Bootp ID is the lower 4 bytes of our ethernet address
628
         *      plus the current time in HZ.
629
         */
630
        BootpID = ((ulong)NetOurEther[2] << 24)
631
                | ((ulong)NetOurEther[3] << 16)
632
                | ((ulong)NetOurEther[4] << 8)
633
                | (ulong)NetOurEther[5];
634
        BootpID += get_timer(0);
635
        bp->bp_id = BootpID;
636
 
637
        /*
638
         * Calculate proper packet lengths taking into account the
639
         * variable size of the options field
640
         */
641
        pktlen = BOOTP_SIZE - sizeof(bp->bp_vend) + ext_len;
642
        iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + ext_len;
643
        NetSetIP(iphdr, 0xffffffffL, PORT_BOOTPS, PORT_BOOTPC, iplen);
644
        NetSetTimeout(SELECT_TIMEOUT * CFG_HZ, BootpTimeout);
645
 
646
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
647
        dhcp_state = SELECTING;
648
        NetSetHandler(DhcpHandler);
649
#else
650
        NetSetHandler(BootpHandler);
651
#endif  /* CFG_CMD_DHCP */
652
        NetSendPacket(NetTxPacket, pktlen);
653
}
654
 
655
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
656
void DhcpOptionsProcess(char *popt)
657
{
658
        char *end = popt + BOOTP_HDR_SIZE;
659
        int oplen, size;
660
 
661
        while ( popt < end && *popt != 0xff ) {
662
                oplen = *(popt + 1);
663
                switch(*popt) {
664
                        case  1:
665
                                NetOurSubnetMask = *(IPaddr_t *)(popt + 2);
666
                                break;
667
                        case  3:
668
                                NetOurGatewayIP = *(IPaddr_t *)(popt + 2);
669
                                break;
670
                        case  6:
671
                                NetOurDNSIP = *(IPaddr_t *)(popt +2);
672
                                break;
673
                        case 12:
674
                                size = truncate_sz ("Host Name",
675
                                                    sizeof(NetOurHostName),
676
                                                    oplen);
677
                                memcpy(&NetOurHostName, popt+2, size);
678
                                NetOurHostName[size] = 0 ;
679
                                break;
680
                        case 15:                /* Ignore Domain Name Option */
681
                                break;
682
                        case 17:
683
                                size = truncate_sz ("Root Path",
684
                                                    sizeof(NetOurRootPath),
685
                                                    oplen);
686
                                memcpy(&NetOurRootPath, popt+2, size);
687
                                NetOurRootPath[size] = 0 ;
688
                                break;
689
                        case 51:
690
                                dhcp_leasetime = *(unsigned int *)(popt + 2);
691
                                break;
692
                        case 53:                /* Ignore Message Type Option */
693
                                break;
694
                        case 54:
695
                                NetServerIP = *(IPaddr_t *)(popt+2);
696
                                break;
697
                        case 58:                /* Ignore Renewal Time Option */
698
                                break;
699
                        case 59:                /* Ignore Rebinding Time Option */
700
                                break;
701
                        default:
702
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
703
                            if (dhcp_vendorex_proc(popt))
704
                                break;
705
#endif
706
                                printf("*** Unhandled DHCP Option in OFFER/ACK: %d\n",
707
                                        *popt);
708
                                break;
709
                }
710
                popt += oplen + 2;      /* Process next option */
711
        }
712
}
713
 
714
static int DhcpMessageType(unsigned char *popt)
715
{
716
        if ((*(uint *)popt) != BOOTP_VENDOR_MAGIC)
717
                return -1;
718
 
719
        popt += 4;
720
        while ( *popt != 0xff ) {
721
                if ( *popt == 53 )      /* DHCP Message Type */
722
                        return *(popt + 2);
723
                popt += *(popt + 1) + 2;        /* Scan through all options */
724
        }
725
        return -1;
726
}
727
 
728
void DhcpSendRequestPkt(Bootp_t *bp_offer)
729
{
730
        volatile uchar *pkt, *iphdr;
731
        Bootp_t *bp;
732
        int pktlen, iplen, extlen;
733
 
734
        debug ("DhcpSendRequestPkt: Sending DHCPREQUEST\n");
735
        pkt = NetTxPacket;
736
        memset ((void*)pkt, 0, PKTSIZE);
737
 
738
        NetSetEther(pkt, NetBcastAddr, PROT_IP);
739
        pkt += ETHER_HDR_SIZE;
740
 
741
        iphdr = pkt;            /* We'll need this later to set proper pkt size */
742
        pkt += IP_HDR_SIZE;
743
 
744
        bp = (Bootp_t *)pkt;
745
        bp->bp_op = OP_BOOTREQUEST;
746
        bp->bp_htype = HWT_ETHER;
747
        bp->bp_hlen = HWL_ETHER;
748
        bp->bp_hops = 0;
749
        bp->bp_secs = SWAP16( get_timer(0) / CFG_HZ);
750
        bp->bp_ciaddr =  bp_offer->bp_ciaddr;
751
        bp->bp_yiaddr =  bp_offer->bp_yiaddr;
752
        bp->bp_siaddr =  bp_offer->bp_siaddr;
753
        bp->bp_giaddr =  bp_offer->bp_giaddr;
754
        NetCopyEther(bp->bp_chaddr, NetOurEther);
755
 
756
        /*
757
         * ID is the id of the OFFER packet
758
         */
759
 
760
        bp->bp_id = bp_offer->bp_id;
761
 
762
        /*
763
         * Copy options from OFFER packet if present
764
         */
765
        extlen = DhcpExtended(bp->bp_vend, DHCP_REQUEST, NetServerIP, bp->bp_yiaddr);
766
 
767
        pktlen = BOOTP_SIZE - sizeof(bp->bp_vend) + extlen;
768
        iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + extlen;
769
        NetSetIP(iphdr, 0xffffffffL, PORT_BOOTPS, PORT_BOOTPC, iplen);
770
 
771
        debug ("Transmitting DHCPREQUEST packet: len = %d\n", pktlen);
772
        NetSendPacket(NetTxPacket, pktlen);
773
}
774
 
775
/*
776
 *      Handle DHCP received packets.
777
 */
778
static void
779
DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
780
{
781
        Bootp_t *bp = (Bootp_t *)pkt;
782
 
783
        debug ("DHCPHandler: got packet: (src=%d, dst=%d, len=%d) state: %d\n",
784
                src, dest, len, dhcp_state);
785
 
786
        if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
787
                return;
788
 
789
        debug ("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d) state: %d\n",
790
                src, dest, len, dhcp_state);
791
 
792
        switch (dhcp_state) {
793
        case SELECTING:
794
                /*
795
                 * Wait an appropriate time for any potential DHCPOFFER packets
796
                 * to arrive.  Then select one, and generate DHCPREQUEST response.
797
                 * If filename is in format we recognize, assume it is a valid
798
                 * OFFER from a server we want.
799
                 */
800
                debug ("DHCP: state=SELECTING bp_file: \"%s\"\n", bp->bp_file);
801
#ifdef CFG_BOOTFILE_PREFIX
802
                if (strncmp(bp->bp_file,
803
                            CFG_BOOTFILE_PREFIX,
804
                            strlen(CFG_BOOTFILE_PREFIX)) == 0 ) {
805
#endif  /* CFG_BOOTFILE_PREFIX */
806
 
807
                        debug ("TRANSITIONING TO REQUESTING STATE\n");
808
                        dhcp_state = REQUESTING;
809
#if 0
810
                        if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC)
811
                                DhcpOptionsProcess(&bp->bp_vend[4]);
812
 
813
#endif
814
                        BootpCopyNetParams(bp); /* Store net params from reply */
815
 
816
                        NetSetTimeout(TIMEOUT * CFG_HZ, BootpTimeout);
817
                        DhcpSendRequestPkt(bp);
818
#ifdef CFG_BOOTFILE_PREFIX
819
                }
820
#endif  /* CFG_BOOTFILE_PREFIX */
821
 
822
                return;
823
                break;
824
        case REQUESTING:
825
                debug ("DHCP State: REQUESTING\n");
826
 
827
                if ( DhcpMessageType(bp->bp_vend) == DHCP_ACK ) {
828
                        char *s;
829
 
830
                        if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC)
831
                                DhcpOptionsProcess(&bp->bp_vend[4]);
832
                        BootpCopyNetParams(bp); /* Store net params from reply */
833
                        dhcp_state = BOUND;
834
                        printf("DHCP client bound to address ");
835
                        print_IPaddr(NetOurIP);
836
                        printf("\n");
837
 
838
                        /* Obey the 'autoload' setting */
839
                        if (((s = getenv("autoload")) != NULL) && (*s == 'n')) {
840
                                NetState = NETLOOP_SUCCESS;
841
                                return;
842
                        }
843
                        /* Send ARP request to get TFTP server ethernet address.
844
                         * This automagically starts TFTP, too.
845
                         */
846
                        ArpRequest();
847
                        return;
848
                }
849
                break;
850
        default:
851
                printf("DHCP: INVALID STATE\n");
852
                break;
853
        }
854
 
855
}
856
 
857
void DhcpRequest(void)
858
{
859
        BootpRequest();
860
}
861
#endif  /* CFG_CMD_DHCP */
862
 
863
#endif /* CFG_CMD_NET */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.