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

Subversion Repositories openrisc

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

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

powered by: WebSVN 2.1.0

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