~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/net/bootp.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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
 *      Copyright 2000-2004 Wolfgang Denk, wd@denx.de
 
9
 */
 
10
 
 
11
#include <common.h>
 
12
#include <command.h>
 
13
#include <net.h>
 
14
#include "bootp.h"
 
15
#include "tftp.h"
 
16
#include "nfs.h"
 
17
#ifdef CONFIG_STATUS_LED
 
18
#include <status_led.h>
 
19
#endif
 
20
#ifdef CONFIG_BOOTP_RANDOM_DELAY
 
21
#include "net_rand.h"
 
22
#endif
 
23
 
 
24
#define BOOTP_VENDOR_MAGIC      0x63825363      /* RFC1048 Magic Cookie */
 
25
 
 
26
#define TIMEOUT         5000UL  /* Milliseconds before trying BOOTP again */
 
27
#ifndef CONFIG_NET_RETRY_COUNT
 
28
# define TIMEOUT_COUNT  5               /* # of timeouts before giving up */
 
29
#else
 
30
# define TIMEOUT_COUNT  (CONFIG_NET_RETRY_COUNT)
 
31
#endif
 
32
 
 
33
#define PORT_BOOTPS     67              /* BOOTP server UDP port */
 
34
#define PORT_BOOTPC     68              /* BOOTP client UDP port */
 
35
 
 
36
#ifndef CONFIG_DHCP_MIN_EXT_LEN         /* minimal length of extension list */
 
37
#define CONFIG_DHCP_MIN_EXT_LEN 64
 
38
#endif
 
39
 
 
40
ulong           BootpID;
 
41
int             BootpTry;
 
42
 
 
43
#if defined(CONFIG_CMD_DHCP)
 
44
static dhcp_state_t dhcp_state = INIT;
 
45
static unsigned long dhcp_leasetime;
 
46
static IPaddr_t NetDHCPServerIP;
 
47
static void DhcpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
 
48
                        unsigned len);
 
49
 
 
50
/* For Debug */
 
51
#if 0
 
52
static char *dhcpmsg2str(int type)
 
53
{
 
54
        switch (type) {
 
55
        case 1:  return "DHCPDISCOVER"; break;
 
56
        case 2:  return "DHCPOFFER";    break;
 
57
        case 3:  return "DHCPREQUEST";  break;
 
58
        case 4:  return "DHCPDECLINE";  break;
 
59
        case 5:  return "DHCPACK";      break;
 
60
        case 6:  return "DHCPNACK";     break;
 
61
        case 7:  return "DHCPRELEASE";  break;
 
62
        default: return "UNKNOWN/INVALID MSG TYPE"; break;
 
63
        }
 
64
}
 
65
#endif
 
66
#endif
 
67
 
 
68
static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len)
 
69
{
 
70
        struct Bootp_t *bp = (struct Bootp_t *) pkt;
 
71
        int retval = 0;
 
72
 
 
73
        if (dest != PORT_BOOTPC || src != PORT_BOOTPS)
 
74
                retval = -1;
 
75
        else if (len < sizeof(struct Bootp_t) - OPT_FIELD_SIZE)
 
76
                retval = -2;
 
77
        else if (bp->bp_op != OP_BOOTREQUEST &&
 
78
                        bp->bp_op != OP_BOOTREPLY &&
 
79
                        bp->bp_op != DHCP_OFFER &&
 
80
                        bp->bp_op != DHCP_ACK &&
 
81
                        bp->bp_op != DHCP_NAK)
 
82
                retval = -3;
 
83
        else if (bp->bp_htype != HWT_ETHER)
 
84
                retval = -4;
 
85
        else if (bp->bp_hlen != HWL_ETHER)
 
86
                retval = -5;
 
87
        else if (NetReadLong((ulong *)&bp->bp_id) != BootpID)
 
88
                retval = -6;
 
89
 
 
90
        debug("Filtering pkt = %d\n", retval);
 
91
 
 
92
        return retval;
 
93
}
 
94
 
 
95
/*
 
96
 * Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet
 
97
 */
 
98
static void BootpCopyNetParams(struct Bootp_t *bp)
 
99
{
 
100
#if !defined(CONFIG_BOOTP_SERVERIP)
 
101
        IPaddr_t tmp_ip;
 
102
 
 
103
        NetCopyIP(&tmp_ip, &bp->bp_siaddr);
 
104
        if (tmp_ip != 0)
 
105
                NetCopyIP(&NetServerIP, &bp->bp_siaddr);
 
106
        memcpy(NetServerEther, ((struct ethernet_hdr *)NetRxPacket)->et_src, 6);
 
107
#endif
 
108
        NetCopyIP(&NetOurIP, &bp->bp_yiaddr);
 
109
        if (strlen(bp->bp_file) > 0)
 
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
static int truncate_sz(const char *name, int maxlen, int curlen)
 
123
{
 
124
        if (curlen >= maxlen) {
 
125
                printf("*** WARNING: %s is too long (%d - max: %d)"
 
126
                        " - truncated\n", name, curlen, maxlen);
 
127
                curlen = maxlen - 1;
 
128
        }
 
129
        return curlen;
 
130
}
 
131
 
 
132
#if !defined(CONFIG_CMD_DHCP)
 
133
 
 
134
static void BootpVendorFieldProcess(u8 *ext)
 
135
{
 
136
        int size = *(ext + 1);
 
137
 
 
138
        debug("[BOOTP] Processing extension %d... (%d bytes)\n", *ext,
 
139
                *(ext + 1));
 
140
 
 
141
        NetBootFileSize = 0;
 
142
 
 
143
        switch (*ext) {
 
144
                /* Fixed length fields */
 
145
        case 1:                 /* Subnet mask */
 
146
                if (NetOurSubnetMask == 0)
 
147
                        NetCopyIP(&NetOurSubnetMask, (IPaddr_t *) (ext + 2));
 
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
                        NetCopyIP(&NetOurGatewayIP, (IPaddr_t *) (ext + 2));
 
155
                break;
 
156
        case 4:                 /* Time server - Not yet supported */
 
157
                break;
 
158
        case 5:                 /* IEN-116 name server - Not yet supported */
 
159
                break;
 
160
        case 6:
 
161
                if (NetOurDNSIP == 0)
 
162
                        NetCopyIP(&NetOurDNSIP, (IPaddr_t *) (ext + 2));
 
163
#if defined(CONFIG_BOOTP_DNS2)
 
164
                if ((NetOurDNS2IP == 0) && (size > 4))
 
165
                        NetCopyIP(&NetOurDNS2IP, (IPaddr_t *) (ext + 2 + 4));
 
166
#endif
 
167
                break;
 
168
        case 7:                 /* Log server - Not yet supported */
 
169
                break;
 
170
        case 8:                 /* Cookie/Quote server - Not yet supported */
 
171
                break;
 
172
        case 9:                 /* LPR server - Not yet supported */
 
173
                break;
 
174
        case 10:                /* Impress server - Not yet supported */
 
175
                break;
 
176
        case 11:                /* RPL server - Not yet supported */
 
177
                break;
 
178
        case 12:                /* Host name */
 
179
                if (NetOurHostName[0] == 0) {
 
180
                        size = truncate_sz("Host Name",
 
181
                                sizeof(NetOurHostName), size);
 
182
                        memcpy(&NetOurHostName, ext + 2, size);
 
183
                        NetOurHostName[size] = 0;
 
184
                }
 
185
                break;
 
186
        case 13:                /* Boot file size */
 
187
                if (size == 2)
 
188
                        NetBootFileSize = ntohs(*(ushort *) (ext + 2));
 
189
                else if (size == 4)
 
190
                        NetBootFileSize = ntohl(*(ulong *) (ext + 2));
 
191
                break;
 
192
        case 14:                /* Merit dump file - Not yet supported */
 
193
                break;
 
194
        case 15:                /* Domain name - Not yet supported */
 
195
                break;
 
196
        case 16:                /* Swap server - Not yet supported */
 
197
                break;
 
198
        case 17:                /* Root path */
 
199
                if (NetOurRootPath[0] == 0) {
 
200
                        size = truncate_sz("Root Path",
 
201
                                sizeof(NetOurRootPath), size);
 
202
                        memcpy(&NetOurRootPath, ext + 2, size);
 
203
                        NetOurRootPath[size] = 0;
 
204
                }
 
205
                break;
 
206
        case 18:                /* Extension path - Not yet supported */
 
207
                /*
 
208
                 * This can be used to send the information of the
 
209
                 * vendor area in another file that the client can
 
210
                 * access via TFTP.
 
211
                 */
 
212
                break;
 
213
                /* IP host layer fields */
 
214
        case 40:                /* NIS Domain name */
 
215
                if (NetOurNISDomain[0] == 0) {
 
216
                        size = truncate_sz("NIS Domain Name",
 
217
                                sizeof(NetOurNISDomain), size);
 
218
                        memcpy(&NetOurNISDomain, ext + 2, size);
 
219
                        NetOurNISDomain[size] = 0;
 
220
                }
 
221
                break;
 
222
#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER)
 
223
        case 42:        /* NTP server IP */
 
224
                NetCopyIP(&NetNtpServerIP, (IPaddr_t *) (ext + 2));
 
225
                break;
 
226
#endif
 
227
                /* Application layer fields */
 
228
        case 43:                /* Vendor specific info - Not yet supported */
 
229
                /*
 
230
                 * Binary information to exchange specific
 
231
                 * product information.
 
232
                 */
 
233
                break;
 
234
                /* Reserved (custom) fields (128..254) */
 
235
        }
 
236
}
 
237
 
 
238
static void BootpVendorProcess(u8 *ext, int size)
 
239
{
 
240
        u8 *end = ext + size;
 
241
 
 
242
        debug("[BOOTP] Checking extension (%d bytes)...\n", size);
 
243
 
 
244
        while ((ext < end) && (*ext != 0xff)) {
 
245
                if (*ext == 0) {
 
246
                        ext++;
 
247
                } else {
 
248
                        u8 *opt = ext;
 
249
 
 
250
                        ext += ext[1] + 2;
 
251
                        if (ext <= end)
 
252
                                BootpVendorFieldProcess(opt);
 
253
                }
 
254
        }
 
255
 
 
256
        debug("[BOOTP] Received fields:\n");
 
257
        if (NetOurSubnetMask)
 
258
                debug("NetOurSubnetMask : %pI4\n", &NetOurSubnetMask);
 
259
 
 
260
        if (NetOurGatewayIP)
 
261
                debug("NetOurGatewayIP  : %pI4", &NetOurGatewayIP);
 
262
 
 
263
        if (NetBootFileSize)
 
264
                debug("NetBootFileSize : %d\n", NetBootFileSize);
 
265
 
 
266
        if (NetOurHostName[0])
 
267
                debug("NetOurHostName  : %s\n", NetOurHostName);
 
268
 
 
269
        if (NetOurRootPath[0])
 
270
                debug("NetOurRootPath  : %s\n", NetOurRootPath);
 
271
 
 
272
        if (NetOurNISDomain[0])
 
273
                debug("NetOurNISDomain : %s\n", NetOurNISDomain);
 
274
 
 
275
        if (NetBootFileSize)
 
276
                debug("NetBootFileSize: %d\n", NetBootFileSize);
 
277
 
 
278
#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER)
 
279
        if (NetNtpServerIP)
 
280
                debug("NetNtpServerIP : %pI4\n", &NetNtpServerIP);
 
281
#endif
 
282
}
 
283
 
 
284
/*
 
285
 *      Handle a BOOTP received packet.
 
286
 */
 
287
static void
 
288
BootpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
 
289
             unsigned len)
 
290
{
 
291
        struct Bootp_t *bp;
 
292
 
 
293
        debug("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%zu)\n",
 
294
                src, dest, len, sizeof(struct Bootp_t));
 
295
 
 
296
        bp = (struct Bootp_t *)pkt;
 
297
 
 
298
        /* Filter out pkts we don't want */
 
299
        if (BootpCheckPkt(pkt, dest, src, len))
 
300
                return;
 
301
 
 
302
        /*
 
303
         *      Got a good BOOTP reply.  Copy the data into our variables.
 
304
         */
 
305
#ifdef CONFIG_STATUS_LED
 
306
        status_led_set(STATUS_LED_BOOT, STATUS_LED_OFF);
 
307
#endif
 
308
 
 
309
        BootpCopyNetParams(bp);         /* Store net parameters from reply */
 
310
 
 
311
        /* Retrieve extended information (we must parse the vendor area) */
 
312
        if (NetReadLong((ulong *)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC))
 
313
                BootpVendorProcess((uchar *)&bp->bp_vend[4], len);
 
314
 
 
315
        NetSetTimeout(0, (thand_f *)0);
 
316
        bootstage_mark_name(BOOTSTAGE_ID_BOOTP_STOP, "bootp_stop");
 
317
 
 
318
        debug("Got good BOOTP\n");
 
319
 
 
320
        net_auto_load();
 
321
}
 
322
#endif
 
323
 
 
324
/*
 
325
 *      Timeout on BOOTP/DHCP request.
 
326
 */
 
327
static void
 
328
BootpTimeout(void)
 
329
{
 
330
        if (BootpTry >= TIMEOUT_COUNT) {
 
331
#ifdef CONFIG_BOOTP_MAY_FAIL
 
332
                puts("\nRetry count exceeded\n");
 
333
                net_set_state(NETLOOP_FAIL);
 
334
#else
 
335
                puts("\nRetry count exceeded; starting again\n");
 
336
                NetStartAgain();
 
337
#endif
 
338
        } else {
 
339
                NetSetTimeout(TIMEOUT, BootpTimeout);
 
340
                BootpRequest();
 
341
        }
 
342
}
 
343
 
 
344
#define put_vci(e, str)                                         \
 
345
        do {                                                    \
 
346
                size_t vci_strlen = strlen(str);                \
 
347
                *e++ = 60;      /* Vendor Class Identifier */   \
 
348
                *e++ = vci_strlen;                              \
 
349
                memcpy(e, str, vci_strlen);                     \
 
350
                e += vci_strlen;                                \
 
351
        } while (0)
 
352
 
 
353
/*
 
354
 *      Initialize BOOTP extension fields in the request.
 
355
 */
 
356
#if defined(CONFIG_CMD_DHCP)
 
357
static int DhcpExtended(u8 *e, int message_type, IPaddr_t ServerID,
 
358
                        IPaddr_t RequestedIP)
 
359
{
 
360
        u8 *start = e;
 
361
        u8 *cnt;
 
362
#if defined(CONFIG_BOOTP_PXE)
 
363
        char *uuid;
 
364
        u16 clientarch;
 
365
#endif
 
366
 
 
367
#if defined(CONFIG_BOOTP_VENDOREX)
 
368
        u8 *x;
 
369
#endif
 
370
#if defined(CONFIG_BOOTP_SEND_HOSTNAME)
 
371
        char *hostname;
 
372
#endif
 
373
 
 
374
        *e++ = 99;              /* RFC1048 Magic Cookie */
 
375
        *e++ = 130;
 
376
        *e++ = 83;
 
377
        *e++ = 99;
 
378
 
 
379
        *e++ = 53;              /* DHCP Message Type */
 
380
        *e++ = 1;
 
381
        *e++ = message_type;
 
382
 
 
383
        *e++ = 57;              /* Maximum DHCP Message Size */
 
384
        *e++ = 2;
 
385
        *e++ = (576 - 312 + OPT_FIELD_SIZE) >> 8;
 
386
        *e++ = (576 - 312 + OPT_FIELD_SIZE) & 0xff;
 
387
 
 
388
        if (ServerID) {
 
389
                int tmp = ntohl(ServerID);
 
390
 
 
391
                *e++ = 54;      /* ServerID */
 
392
                *e++ = 4;
 
393
                *e++ = tmp >> 24;
 
394
                *e++ = tmp >> 16;
 
395
                *e++ = tmp >> 8;
 
396
                *e++ = tmp & 0xff;
 
397
        }
 
398
 
 
399
        if (RequestedIP) {
 
400
                int tmp = ntohl(RequestedIP);
 
401
 
 
402
                *e++ = 50;      /* Requested IP */
 
403
                *e++ = 4;
 
404
                *e++ = tmp >> 24;
 
405
                *e++ = tmp >> 16;
 
406
                *e++ = tmp >> 8;
 
407
                *e++ = tmp & 0xff;
 
408
        }
 
409
#if defined(CONFIG_BOOTP_SEND_HOSTNAME)
 
410
        hostname = getenv("hostname");
 
411
        if (hostname) {
 
412
                int hostnamelen = strlen(hostname);
 
413
 
 
414
                *e++ = 12;      /* Hostname */
 
415
                *e++ = hostnamelen;
 
416
                memcpy(e, hostname, hostnamelen);
 
417
                e += hostnamelen;
 
418
        }
 
419
#endif
 
420
 
 
421
#if defined(CONFIG_BOOTP_PXE)
 
422
        clientarch = CONFIG_BOOTP_PXE_CLIENTARCH;
 
423
        *e++ = 93;      /* Client System Architecture */
 
424
        *e++ = 2;
 
425
        *e++ = (clientarch >> 8) & 0xff;
 
426
        *e++ = clientarch & 0xff;
 
427
 
 
428
        *e++ = 94;      /* Client Network Interface Identifier */
 
429
        *e++ = 3;
 
430
        *e++ = 1;       /* type field for UNDI */
 
431
        *e++ = 0;       /* major revision */
 
432
        *e++ = 0;       /* minor revision */
 
433
 
 
434
        uuid = getenv("pxeuuid");
 
435
 
 
436
        if (uuid) {
 
437
                if (uuid_str_valid(uuid)) {
 
438
                        *e++ = 97;      /* Client Machine Identifier */
 
439
                        *e++ = 17;
 
440
                        *e++ = 0;       /* type 0 - UUID */
 
441
 
 
442
                        uuid_str_to_bin(uuid, e, UUID_STR_FORMAT_STD);
 
443
                        e += 16;
 
444
                } else {
 
445
                        printf("Invalid pxeuuid: %s\n", uuid);
 
446
                }
 
447
        }
 
448
#endif
 
449
 
 
450
#ifdef CONFIG_BOOTP_VCI_STRING
 
451
        put_vci(e, CONFIG_BOOTP_VCI_STRING);
 
452
#endif
 
453
 
 
454
#if defined(CONFIG_BOOTP_VENDOREX)
 
455
        x = dhcp_vendorex_prep(e);
 
456
        if (x)
 
457
                return x - start;
 
458
#endif
 
459
 
 
460
        *e++ = 55;              /* Parameter Request List */
 
461
         cnt = e++;             /* Pointer to count of requested items */
 
462
        *cnt = 0;
 
463
#if defined(CONFIG_BOOTP_SUBNETMASK)
 
464
        *e++  = 1;              /* Subnet Mask */
 
465
        *cnt += 1;
 
466
#endif
 
467
#if defined(CONFIG_BOOTP_TIMEOFFSET)
 
468
        *e++  = 2;
 
469
        *cnt += 1;
 
470
#endif
 
471
#if defined(CONFIG_BOOTP_GATEWAY)
 
472
        *e++  = 3;              /* Router Option */
 
473
        *cnt += 1;
 
474
#endif
 
475
#if defined(CONFIG_BOOTP_DNS)
 
476
        *e++  = 6;              /* DNS Server(s) */
 
477
        *cnt += 1;
 
478
#endif
 
479
#if defined(CONFIG_BOOTP_HOSTNAME)
 
480
        *e++  = 12;             /* Hostname */
 
481
        *cnt += 1;
 
482
#endif
 
483
#if defined(CONFIG_BOOTP_BOOTFILESIZE)
 
484
        *e++  = 13;             /* Boot File Size */
 
485
        *cnt += 1;
 
486
#endif
 
487
#if defined(CONFIG_BOOTP_BOOTPATH)
 
488
        *e++  = 17;             /* Boot path */
 
489
        *cnt += 1;
 
490
#endif
 
491
#if defined(CONFIG_BOOTP_NISDOMAIN)
 
492
        *e++  = 40;             /* NIS Domain name request */
 
493
        *cnt += 1;
 
494
#endif
 
495
#if defined(CONFIG_BOOTP_NTPSERVER)
 
496
        *e++  = 42;
 
497
        *cnt += 1;
 
498
#endif
 
499
        /* no options, so back up to avoid sending an empty request list */
 
500
        if (*cnt == 0)
 
501
                e -= 2;
 
502
 
 
503
        *e++  = 255;            /* End of the list */
 
504
 
 
505
        /* Pad to minimal length */
 
506
#ifdef  CONFIG_DHCP_MIN_EXT_LEN
 
507
        while ((e - start) < CONFIG_DHCP_MIN_EXT_LEN)
 
508
                *e++ = 0;
 
509
#endif
 
510
 
 
511
        return e - start;
 
512
}
 
513
 
 
514
#else
 
515
/*
 
516
 * Warning: no field size check - change CONFIG_BOOTP_* at your own risk!
 
517
 */
 
518
static int BootpExtended(u8 *e)
 
519
{
 
520
        u8 *start = e;
 
521
 
 
522
        *e++ = 99;              /* RFC1048 Magic Cookie */
 
523
        *e++ = 130;
 
524
        *e++ = 83;
 
525
        *e++ = 99;
 
526
 
 
527
#if defined(CONFIG_CMD_DHCP)
 
528
        *e++ = 53;              /* DHCP Message Type */
 
529
        *e++ = 1;
 
530
        *e++ = DHCP_DISCOVER;
 
531
 
 
532
        *e++ = 57;              /* Maximum DHCP Message Size */
 
533
        *e++ = 2;
 
534
        *e++ = (576 - 312 + OPT_FIELD_SIZE) >> 16;
 
535
        *e++ = (576 - 312 + OPT_FIELD_SIZE) & 0xff;
 
536
#endif
 
537
 
 
538
#if defined(CONFIG_BOOTP_VCI_STRING) || \
 
539
        (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_NET_VCI_STRING))
 
540
#ifdef CONFIG_SPL_BUILD
 
541
        put_vci(e, CONFIG_SPL_NET_VCI_STRING);
 
542
#else
 
543
        put_vci(e, CONFIG_BOOTP_VCI_STRING);
 
544
#endif
 
545
#endif
 
546
 
 
547
#if defined(CONFIG_BOOTP_SUBNETMASK)
 
548
        *e++ = 1;               /* Subnet mask request */
 
549
        *e++ = 4;
 
550
        e   += 4;
 
551
#endif
 
552
 
 
553
#if defined(CONFIG_BOOTP_GATEWAY)
 
554
        *e++ = 3;               /* Default gateway request */
 
555
        *e++ = 4;
 
556
        e   += 4;
 
557
#endif
 
558
 
 
559
#if defined(CONFIG_BOOTP_DNS)
 
560
        *e++ = 6;               /* Domain Name Server */
 
561
        *e++ = 4;
 
562
        e   += 4;
 
563
#endif
 
564
 
 
565
#if defined(CONFIG_BOOTP_HOSTNAME)
 
566
        *e++ = 12;              /* Host name request */
 
567
        *e++ = 32;
 
568
        e   += 32;
 
569
#endif
 
570
 
 
571
#if defined(CONFIG_BOOTP_BOOTFILESIZE)
 
572
        *e++ = 13;              /* Boot file size */
 
573
        *e++ = 2;
 
574
        e   += 2;
 
575
#endif
 
576
 
 
577
#if defined(CONFIG_BOOTP_BOOTPATH)
 
578
        *e++ = 17;              /* Boot path */
 
579
        *e++ = 32;
 
580
        e   += 32;
 
581
#endif
 
582
 
 
583
#if defined(CONFIG_BOOTP_NISDOMAIN)
 
584
        *e++ = 40;              /* NIS Domain name request */
 
585
        *e++ = 32;
 
586
        e   += 32;
 
587
#endif
 
588
#if defined(CONFIG_BOOTP_NTPSERVER)
 
589
        *e++ = 42;
 
590
        *e++ = 4;
 
591
        e   += 4;
 
592
#endif
 
593
 
 
594
        *e++ = 255;             /* End of the list */
 
595
 
 
596
        return e - start;
 
597
}
 
598
#endif
 
599
 
 
600
void
 
601
BootpRequest(void)
 
602
{
 
603
        uchar *pkt, *iphdr;
 
604
        struct Bootp_t *bp;
 
605
        int extlen, pktlen, iplen;
 
606
        int eth_hdr_size;
 
607
#ifdef CONFIG_BOOTP_RANDOM_DELAY
 
608
        ulong i, rand_ms;
 
609
#endif
 
610
 
 
611
        bootstage_mark_name(BOOTSTAGE_ID_BOOTP_START, "bootp_start");
 
612
#if defined(CONFIG_CMD_DHCP)
 
613
        dhcp_state = INIT;
 
614
#endif
 
615
 
 
616
#ifdef CONFIG_BOOTP_RANDOM_DELAY                /* Random BOOTP delay */
 
617
        if (BootpTry == 0)
 
618
                srand_mac();
 
619
 
 
620
        if (BootpTry <= 2)      /* Start with max 1024 * 1ms */
 
621
                rand_ms = rand() >> (22 - BootpTry);
 
622
        else            /* After 3rd BOOTP request max 8192 * 1ms */
 
623
                rand_ms = rand() >> 19;
 
624
 
 
625
        printf("Random delay: %ld ms...\n", rand_ms);
 
626
        for (i = 0; i < rand_ms; i++)
 
627
                udelay(1000); /*Wait 1ms*/
 
628
 
 
629
#endif  /* CONFIG_BOOTP_RANDOM_DELAY */
 
630
 
 
631
        printf("BOOTP broadcast %d\n", ++BootpTry);
 
632
        pkt = NetTxPacket;
 
633
        memset((void *)pkt, 0, PKTSIZE);
 
634
 
 
635
        eth_hdr_size = NetSetEther(pkt, NetBcastAddr, PROT_IP);
 
636
        pkt += eth_hdr_size;
 
637
 
 
638
        /*
 
639
         * Next line results in incorrect packet size being transmitted,
 
640
         * resulting in errors in some DHCP servers, reporting missing bytes.
 
641
         * Size must be set in packet header after extension length has been
 
642
         * determined.
 
643
         * C. Hallinan, DS4.COM, Inc.
 
644
         */
 
645
        /* net_set_udp_header(pkt, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC,
 
646
                sizeof (struct Bootp_t)); */
 
647
        iphdr = pkt;    /* We need this later for net_set_udp_header() */
 
648
        pkt += IP_UDP_HDR_SIZE;
 
649
 
 
650
        bp = (struct Bootp_t *)pkt;
 
651
        bp->bp_op = OP_BOOTREQUEST;
 
652
        bp->bp_htype = HWT_ETHER;
 
653
        bp->bp_hlen = HWL_ETHER;
 
654
        bp->bp_hops = 0;
 
655
        bp->bp_secs = htons(get_timer(0) / 1000);
 
656
        NetWriteIP(&bp->bp_ciaddr, 0);
 
657
        NetWriteIP(&bp->bp_yiaddr, 0);
 
658
        NetWriteIP(&bp->bp_siaddr, 0);
 
659
        NetWriteIP(&bp->bp_giaddr, 0);
 
660
        memcpy(bp->bp_chaddr, NetOurEther, 6);
 
661
        copy_filename(bp->bp_file, BootFile, sizeof(bp->bp_file));
 
662
 
 
663
        /* Request additional information from the BOOTP/DHCP server */
 
664
#if defined(CONFIG_CMD_DHCP)
 
665
        extlen = DhcpExtended((u8 *)bp->bp_vend, DHCP_DISCOVER, 0, 0);
 
666
#else
 
667
        extlen = BootpExtended((u8 *)bp->bp_vend);
 
668
#endif
 
669
 
 
670
        /*
 
671
         *      Bootp ID is the lower 4 bytes of our ethernet address
 
672
         *      plus the current time in ms.
 
673
         */
 
674
        BootpID = ((ulong)NetOurEther[2] << 24)
 
675
                | ((ulong)NetOurEther[3] << 16)
 
676
                | ((ulong)NetOurEther[4] << 8)
 
677
                | (ulong)NetOurEther[5];
 
678
        BootpID += get_timer(0);
 
679
        BootpID  = htonl(BootpID);
 
680
        NetCopyLong(&bp->bp_id, &BootpID);
 
681
 
 
682
        /*
 
683
         * Calculate proper packet lengths taking into account the
 
684
         * variable size of the options field
 
685
         */
 
686
        iplen = BOOTP_HDR_SIZE - OPT_FIELD_SIZE + extlen;
 
687
        pktlen = eth_hdr_size + IP_UDP_HDR_SIZE + iplen;
 
688
        net_set_udp_header(iphdr, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC, iplen);
 
689
        NetSetTimeout(SELECT_TIMEOUT, BootpTimeout);
 
690
 
 
691
#if defined(CONFIG_CMD_DHCP)
 
692
        dhcp_state = SELECTING;
 
693
        net_set_udp_handler(DhcpHandler);
 
694
#else
 
695
        net_set_udp_handler(BootpHandler);
 
696
#endif
 
697
        NetSendPacket(NetTxPacket, pktlen);
 
698
}
 
699
 
 
700
#if defined(CONFIG_CMD_DHCP)
 
701
static void DhcpOptionsProcess(uchar *popt, struct Bootp_t *bp)
 
702
{
 
703
        uchar *end = popt + BOOTP_HDR_SIZE;
 
704
        int oplen, size;
 
705
#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET)
 
706
        int *to_ptr;
 
707
#endif
 
708
 
 
709
        while (popt < end && *popt != 0xff) {
 
710
                oplen = *(popt + 1);
 
711
                switch (*popt) {
 
712
                case 1:
 
713
                        NetCopyIP(&NetOurSubnetMask, (popt + 2));
 
714
                        break;
 
715
#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET)
 
716
                case 2:         /* Time offset  */
 
717
                        to_ptr = &NetTimeOffset;
 
718
                        NetCopyLong((ulong *)to_ptr, (ulong *)(popt + 2));
 
719
                        NetTimeOffset = ntohl(NetTimeOffset);
 
720
                        break;
 
721
#endif
 
722
                case 3:
 
723
                        NetCopyIP(&NetOurGatewayIP, (popt + 2));
 
724
                        break;
 
725
                case 6:
 
726
                        NetCopyIP(&NetOurDNSIP, (popt + 2));
 
727
#if defined(CONFIG_BOOTP_DNS2)
 
728
                        if (*(popt + 1) > 4)
 
729
                                NetCopyIP(&NetOurDNS2IP, (popt + 2 + 4));
 
730
#endif
 
731
                        break;
 
732
                case 12:
 
733
                        size = truncate_sz("Host Name",
 
734
                                sizeof(NetOurHostName), oplen);
 
735
                        memcpy(&NetOurHostName, popt + 2, size);
 
736
                        NetOurHostName[size] = 0;
 
737
                        break;
 
738
                case 15:        /* Ignore Domain Name Option */
 
739
                        break;
 
740
                case 17:
 
741
                        size = truncate_sz("Root Path",
 
742
                                sizeof(NetOurRootPath), oplen);
 
743
                        memcpy(&NetOurRootPath, popt + 2, size);
 
744
                        NetOurRootPath[size] = 0;
 
745
                        break;
 
746
                case 28:        /* Ignore Broadcast Address Option */
 
747
                        break;
 
748
#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER)
 
749
                case 42:        /* NTP server IP */
 
750
                        NetCopyIP(&NetNtpServerIP, (popt + 2));
 
751
                        break;
 
752
#endif
 
753
                case 51:
 
754
                        NetCopyLong(&dhcp_leasetime, (ulong *) (popt + 2));
 
755
                        break;
 
756
                case 53:        /* Ignore Message Type Option */
 
757
                        break;
 
758
                case 54:
 
759
                        NetCopyIP(&NetDHCPServerIP, (popt + 2));
 
760
                        break;
 
761
                case 58:        /* Ignore Renewal Time Option */
 
762
                        break;
 
763
                case 59:        /* Ignore Rebinding Time Option */
 
764
                        break;
 
765
                case 66:        /* Ignore TFTP server name */
 
766
                        break;
 
767
                case 67:        /* vendor opt bootfile */
 
768
                        /*
 
769
                         * I can't use dhcp_vendorex_proc here because I need
 
770
                         * to write into the bootp packet - even then I had to
 
771
                         * pass the bootp packet pointer into here as the
 
772
                         * second arg
 
773
                         */
 
774
                        size = truncate_sz("Opt Boot File",
 
775
                                            sizeof(bp->bp_file),
 
776
                                            oplen);
 
777
                        if (bp->bp_file[0] == '\0' && size > 0) {
 
778
                                /*
 
779
                                 * only use vendor boot file if we didn't
 
780
                                 * receive a boot file in the main non-vendor
 
781
                                 * part of the packet - god only knows why
 
782
                                 * some vendors chose not to use this perfectly
 
783
                                 * good spot to store the boot file (join on
 
784
                                 * Tru64 Unix) it seems mind bogglingly crazy
 
785
                                 * to me
 
786
                                 */
 
787
                                printf("*** WARNING: using vendor "
 
788
                                        "optional boot file\n");
 
789
                                memcpy(bp->bp_file, popt + 2, size);
 
790
                                bp->bp_file[size] = '\0';
 
791
                        }
 
792
                        break;
 
793
                default:
 
794
#if defined(CONFIG_BOOTP_VENDOREX)
 
795
                        if (dhcp_vendorex_proc(popt))
 
796
                                break;
 
797
#endif
 
798
                        printf("*** Unhandled DHCP Option in OFFER/ACK:"
 
799
                                " %d\n", *popt);
 
800
                        break;
 
801
                }
 
802
                popt += oplen + 2;      /* Process next option */
 
803
        }
 
804
}
 
805
 
 
806
static int DhcpMessageType(unsigned char *popt)
 
807
{
 
808
        if (NetReadLong((ulong *)popt) != htonl(BOOTP_VENDOR_MAGIC))
 
809
                return -1;
 
810
 
 
811
        popt += 4;
 
812
        while (*popt != 0xff) {
 
813
                if (*popt == 53)        /* DHCP Message Type */
 
814
                        return *(popt + 2);
 
815
                popt += *(popt + 1) + 2;        /* Scan through all options */
 
816
        }
 
817
        return -1;
 
818
}
 
819
 
 
820
static void DhcpSendRequestPkt(struct Bootp_t *bp_offer)
 
821
{
 
822
        uchar *pkt, *iphdr;
 
823
        struct Bootp_t *bp;
 
824
        int pktlen, iplen, extlen;
 
825
        int eth_hdr_size;
 
826
        IPaddr_t OfferedIP;
 
827
 
 
828
        debug("DhcpSendRequestPkt: Sending DHCPREQUEST\n");
 
829
        pkt = NetTxPacket;
 
830
        memset((void *)pkt, 0, PKTSIZE);
 
831
 
 
832
        eth_hdr_size = NetSetEther(pkt, NetBcastAddr, PROT_IP);
 
833
        pkt += eth_hdr_size;
 
834
 
 
835
        iphdr = pkt;    /* We'll need this later to set proper pkt size */
 
836
        pkt += IP_UDP_HDR_SIZE;
 
837
 
 
838
        bp = (struct Bootp_t *)pkt;
 
839
        bp->bp_op = OP_BOOTREQUEST;
 
840
        bp->bp_htype = HWT_ETHER;
 
841
        bp->bp_hlen = HWL_ETHER;
 
842
        bp->bp_hops = 0;
 
843
        bp->bp_secs = htons(get_timer(0) / 1000);
 
844
        /* Do not set the client IP, your IP, or server IP yet, since it
 
845
         * hasn't been ACK'ed by the server yet */
 
846
 
 
847
        /*
 
848
         * RFC3046 requires Relay Agents to discard packets with
 
849
         * nonzero and offered giaddr
 
850
         */
 
851
        NetWriteIP(&bp->bp_giaddr, 0);
 
852
 
 
853
        memcpy(bp->bp_chaddr, NetOurEther, 6);
 
854
 
 
855
        /*
 
856
         * ID is the id of the OFFER packet
 
857
         */
 
858
 
 
859
        NetCopyLong(&bp->bp_id, &bp_offer->bp_id);
 
860
 
 
861
        /*
 
862
         * Copy options from OFFER packet if present
 
863
         */
 
864
 
 
865
        /* Copy offered IP into the parameters request list */
 
866
        NetCopyIP(&OfferedIP, &bp_offer->bp_yiaddr);
 
867
        extlen = DhcpExtended((u8 *)bp->bp_vend, DHCP_REQUEST,
 
868
                NetDHCPServerIP, OfferedIP);
 
869
 
 
870
        iplen = BOOTP_HDR_SIZE - OPT_FIELD_SIZE + extlen;
 
871
        pktlen = eth_hdr_size + IP_UDP_HDR_SIZE + iplen;
 
872
        net_set_udp_header(iphdr, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC, iplen);
 
873
 
 
874
#ifdef CONFIG_BOOTP_DHCP_REQUEST_DELAY
 
875
        udelay(CONFIG_BOOTP_DHCP_REQUEST_DELAY);
 
876
#endif  /* CONFIG_BOOTP_DHCP_REQUEST_DELAY */
 
877
        debug("Transmitting DHCPREQUEST packet: len = %d\n", pktlen);
 
878
        NetSendPacket(NetTxPacket, pktlen);
 
879
}
 
880
 
 
881
/*
 
882
 *      Handle DHCP received packets.
 
883
 */
 
884
static void
 
885
DhcpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
 
886
            unsigned len)
 
887
{
 
888
        struct Bootp_t *bp = (struct Bootp_t *)pkt;
 
889
 
 
890
        debug("DHCPHandler: got packet: (src=%d, dst=%d, len=%d) state: %d\n",
 
891
                src, dest, len, dhcp_state);
 
892
 
 
893
        /* Filter out pkts we don't want */
 
894
        if (BootpCheckPkt(pkt, dest, src, len))
 
895
                return;
 
896
 
 
897
        debug("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d) state:"
 
898
                " %d\n", src, dest, len, dhcp_state);
 
899
 
 
900
        switch (dhcp_state) {
 
901
        case SELECTING:
 
902
                /*
 
903
                 * Wait an appropriate time for any potential DHCPOFFER packets
 
904
                 * to arrive.  Then select one, and generate DHCPREQUEST
 
905
                 * response.  If filename is in format we recognize, assume it
 
906
                 * is a valid OFFER from a server we want.
 
907
                 */
 
908
                debug("DHCP: state=SELECTING bp_file: \"%s\"\n", bp->bp_file);
 
909
#ifdef CONFIG_SYS_BOOTFILE_PREFIX
 
910
                if (strncmp(bp->bp_file,
 
911
                            CONFIG_SYS_BOOTFILE_PREFIX,
 
912
                            strlen(CONFIG_SYS_BOOTFILE_PREFIX)) == 0) {
 
913
#endif  /* CONFIG_SYS_BOOTFILE_PREFIX */
 
914
 
 
915
                        debug("TRANSITIONING TO REQUESTING STATE\n");
 
916
                        dhcp_state = REQUESTING;
 
917
 
 
918
                        if (NetReadLong((ulong *)&bp->bp_vend[0]) ==
 
919
                                                htonl(BOOTP_VENDOR_MAGIC))
 
920
                                DhcpOptionsProcess((u8 *)&bp->bp_vend[4], bp);
 
921
 
 
922
                        NetSetTimeout(TIMEOUT, BootpTimeout);
 
923
                        DhcpSendRequestPkt(bp);
 
924
#ifdef CONFIG_SYS_BOOTFILE_PREFIX
 
925
                }
 
926
#endif  /* CONFIG_SYS_BOOTFILE_PREFIX */
 
927
 
 
928
                return;
 
929
                break;
 
930
        case REQUESTING:
 
931
                debug("DHCP State: REQUESTING\n");
 
932
 
 
933
                if (DhcpMessageType((u8 *)bp->bp_vend) == DHCP_ACK) {
 
934
                        if (NetReadLong((ulong *)&bp->bp_vend[0]) ==
 
935
                                                htonl(BOOTP_VENDOR_MAGIC))
 
936
                                DhcpOptionsProcess((u8 *)&bp->bp_vend[4], bp);
 
937
                        /* Store net params from reply */
 
938
                        BootpCopyNetParams(bp);
 
939
                        dhcp_state = BOUND;
 
940
                        printf("DHCP client bound to address %pI4\n",
 
941
                                &NetOurIP);
 
942
                        bootstage_mark_name(BOOTSTAGE_ID_BOOTP_STOP,
 
943
                                "bootp_stop");
 
944
 
 
945
                        net_auto_load();
 
946
                        return;
 
947
                }
 
948
                break;
 
949
        case BOUND:
 
950
                /* DHCP client bound to address */
 
951
                break;
 
952
        default:
 
953
                puts("DHCP: INVALID STATE\n");
 
954
                break;
 
955
        }
 
956
 
 
957
}
 
958
 
 
959
void DhcpRequest(void)
 
960
{
 
961
        BootpRequest();
 
962
}
 
963
#endif  /* CONFIG_CMD_DHCP */