2
* GRUB -- GRand Unified Bootloader
3
* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
/* Based on "src/main.c" in etherboot-5.0.5. */
22
/**************************************************************************
23
ETHERBOOT - BOOTP/TFTP Bootstrap Program
25
Author: Martin Renters
28
Literature dealing with the network protocols:
32
BOOTP - RFC951, RFC2132 (vendor extensions)
33
DHCP - RFC2131, RFC2132 (options)
34
TFTP - RFC1350, RFC2347 (options), RFC2348 (blocksize), RFC2349 (tsize)
35
RPC - RFC1831, RFC1832 (XDR), RFC1833 (rpcbind/portmapper)
36
NFS - RFC1094, RFC1813 (v3, useful for clarifications, not implemented)
38
**************************************************************************/
41
#include <etherboot.h>
46
struct arptable_t arptable[MAX_ARP];
48
/* Set if the user pushes Control-C. */
50
/* Set if an ethernet card is probed and IP addresses are set. */
51
int network_ready = 0;
55
static int vendorext_isvalid;
56
static unsigned long netmask;
57
static struct bootpd_t bootp_data;
58
static unsigned long xid;
59
static unsigned char *end_of_rfc1533 = NULL;
61
#ifndef NO_DHCP_SUPPORT
62
#endif /* NO_DHCP_SUPPORT */
65
static unsigned char vendorext_magic[] = {0xE4, 0x45, 0x74, 0x68};
66
static const unsigned char broadcast[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
68
#ifdef NO_DHCP_SUPPORT
70
static unsigned char rfc1533_cookie[5] = {RFC1533_COOKIE, RFC1533_END};
72
#else /* ! NO_DHCP_SUPPORT */
74
static int dhcp_reply;
75
static in_addr dhcp_server = {0L};
76
static in_addr dhcp_addr = {0L};
77
static unsigned char rfc1533_cookie[] = {RFC1533_COOKIE};
78
static unsigned char rfc1533_end[] = {RFC1533_END};
80
static const unsigned char dhcpdiscover[] =
82
RFC2132_MSG_TYPE, 1, DHCPDISCOVER,
83
RFC2132_MAX_SIZE,2, /* request as much as we can */
84
ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
85
RFC2132_PARAM_LIST, 4, RFC1533_NETMASK, RFC1533_GATEWAY,
86
RFC1533_HOSTNAME, RFC1533_EXTENSIONPATH
89
static const unsigned char dhcprequest[] =
91
RFC2132_MSG_TYPE, 1, DHCPREQUEST,
92
RFC2132_SRV_ID, 4, 0, 0, 0, 0,
93
RFC2132_REQ_ADDR, 4, 0, 0, 0, 0,
94
RFC2132_MAX_SIZE, 2, /* request as much as we can */
95
ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
96
/* request parameters */
98
/* 4 standard + 2 vendortags */
100
/* Standard parameters */
101
RFC1533_NETMASK, RFC1533_GATEWAY,
102
RFC1533_HOSTNAME, RFC1533_EXTENSIONPATH,
103
/* Etherboot vendortags */
104
RFC1533_VENDOR_MAGIC,
105
RFC1533_VENDOR_CONFIGFILE,
108
#endif /* ! NO_DHCP_SUPPORT */
110
static unsigned short ipchksum (unsigned short *ip, int len);
111
static unsigned short udpchksum (struct iphdr *packet);
114
print_network_configuration (void)
117
grub_printf ("No ethernet card found.\n");
118
else if (! network_ready)
119
grub_printf ("Not initialized yet.\n");
122
etherboot_printf ("Address: %@\n", arptable[ARP_CLIENT].ipaddr.s_addr);
123
etherboot_printf ("Netmask: %@\n", netmask);
124
etherboot_printf ("Server: %@\n", arptable[ARP_SERVER].ipaddr.s_addr);
125
etherboot_printf ("Gateway: %@\n", arptable[ARP_GATEWAY].ipaddr.s_addr);
130
/**************************************************************************
131
DEFAULT_NETMASK - Return default netmask for IP address
132
**************************************************************************/
133
static inline unsigned long
134
default_netmask (void)
136
int net = ntohl (arptable[ARP_CLIENT].ipaddr.s_addr) >> 24;
138
return (htonl (0xff000000));
140
return (htonl (0xffff0000));
142
return (htonl (0xffffff00));
145
/* ifconfig - configure network interface. */
147
ifconfig (char *ip, char *sm, char *gw, char *svr)
153
if (! inet_aton (sm, &tmp))
156
netmask = tmp.s_addr;
161
if (! inet_aton (ip, &arptable[ARP_CLIENT].ipaddr))
164
if (! netmask && ! sm)
165
netmask = default_netmask ();
168
if (gw && ! inet_aton (gw, &arptable[ARP_GATEWAY].ipaddr))
171
if (svr && ! inet_aton (svr, &arptable[ARP_SERVER].ipaddr))
176
if (IP_BROADCAST == (netmask | arptable[ARP_CLIENT].ipaddr.s_addr)
177
|| netmask == (netmask | arptable[ARP_CLIENT].ipaddr.s_addr)
188
/**************************************************************************
189
UDP_TRANSMIT - Send a UDP datagram
190
**************************************************************************/
192
udp_transmit (unsigned long destip, unsigned int srcsock,
193
unsigned int destsock, int len, const void *buf)
197
struct arprequest arpreq;
201
ip = (struct iphdr *) buf;
202
udp = (struct udphdr *) ((unsigned long) buf + sizeof (struct iphdr));
203
ip->verhdrlen = 0x45;
205
ip->len = htons (len);
209
ip->protocol = IP_UDP;
211
ip->src.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr;
212
ip->dest.s_addr = destip;
213
ip->chksum = ipchksum ((unsigned short *) buf, sizeof (struct iphdr));
214
udp->src = htons (srcsock);
215
udp->dest = htons (destsock);
216
udp->len = htons (len - sizeof (struct iphdr));
218
udp->chksum = htons (udpchksum (ip));
220
if (udp->chksum == 0)
221
udp->chksum = 0xffff;
223
if (destip == IP_BROADCAST)
225
eth_transmit (broadcast, IP, len, buf);
229
if (((destip & netmask)
230
!= (arptable[ARP_CLIENT].ipaddr.s_addr & netmask))
231
&& arptable[ARP_GATEWAY].ipaddr.s_addr)
232
destip = arptable[ARP_GATEWAY].ipaddr.s_addr;
234
for (arpentry = 0; arpentry < MAX_ARP; arpentry++)
235
if (arptable[arpentry].ipaddr.s_addr == destip)
238
if (arpentry == MAX_ARP)
240
etherboot_printf ("%@ is not in my arp table!\n", destip);
244
for (i = 0; i < ETH_ALEN; i++)
245
if (arptable[arpentry].node[i])
250
/* Need to do arp request. */
252
grub_printf ("arp request.\n");
254
arpreq.hwtype = htons (1);
255
arpreq.protocol = htons (IP);
256
arpreq.hwlen = ETH_ALEN;
258
arpreq.opcode = htons (ARP_REQUEST);
259
grub_memmove (arpreq.shwaddr, arptable[ARP_CLIENT].node,
261
grub_memmove (arpreq.sipaddr, (char *) &arptable[ARP_CLIENT].ipaddr,
263
grub_memset (arpreq.thwaddr, 0, ETH_ALEN);
264
grub_memmove (arpreq.tipaddr, (char *) &destip, sizeof (in_addr));
266
for (retry = 1; retry <= MAX_ARP_RETRIES; retry++)
270
eth_transmit (broadcast, ARP, sizeof (arpreq), &arpreq);
271
timeout = rfc2131_sleep_interval (TIMEOUT, retry);
273
if (await_reply (AWAIT_ARP, arpentry, arpreq.tipaddr, timeout))
284
eth_transmit (arptable[arpentry].node, IP, len, buf);
290
/**************************************************************************
291
TFTP - Download extended BOOTP data, or kernel image
292
**************************************************************************/
294
tftp (const char *name, int (*fnc) (unsigned char *, int, int, int))
297
static unsigned short iport = 2000;
298
unsigned short oport = 0;
299
unsigned short len, block = 0, prevblock = 0;
304
int packetsize = TFTP_DEFAULTSIZE_PACKET;
306
/* Clear out the Rx queue first. It contains nothing of interest,
307
* except possibly ARP requests from the DHCP/TFTP server. We use
308
* polling throughout Etherboot, so some time may have passed since we
309
* last polled the receive queue, which may now be filled with
310
* broadcast packets. This will cause the reply to the packets we are
311
* about to send to be lost immediately. Not very clever. */
312
await_reply (AWAIT_QDRAIN, 0, NULL, 0);
314
tp.opcode = htons (TFTP_RRQ);
315
len = (grub_sprintf ((char *) tp.u.rrq, "%s%coctet%cblksize%c%d",
316
name, 0, 0, 0, TFTP_MAX_PACKET)
317
+ sizeof (tp.ip) + sizeof (tp.udp) + sizeof (tp.opcode) + 1);
318
if (! udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, ++iport,
319
TFTP_PORT, len, &tp))
327
timeout = rfc2131_sleep_interval (block ? TFTP_REXMT : TIMEOUT, retry);
329
timeout = rfc2131_sleep_interval (TIMEOUT, retry);
332
if (! await_reply (AWAIT_TFTP, iport, NULL, timeout))
334
if (! block && retry++ < MAX_TFTP_RETRIES)
336
/* Maybe initial request was lost. */
337
if (! udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
338
++iport, TFTP_PORT, len, &tp))
345
if (block && ((retry += TFTP_REXMT) < TFTP_TIMEOUT))
347
/* We resend our last ack. */
349
grub_printf ("<REXMT>\n");
351
udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
353
TFTP_MIN_PACKET, &tp);
361
tr = (struct tftp_t *) &nic.packet[ETH_HLEN];
362
if (tr->opcode == ntohs (TFTP_ERROR))
364
grub_printf ("TFTP error %d (%s)\n",
365
ntohs (tr->u.err.errcode),
370
if (tr->opcode == ntohs (TFTP_OACK))
372
char *p = tr->u.oack.data, *e;
374
/* Shouldn't happen. */
379
len = ntohs (tr->udp.len) - sizeof (struct udphdr) - 2;
380
if (len > TFTP_MAX_PACKET)
384
while (*p != '\000' && p < e)
386
if (! grub_strcmp ("blksize", p))
389
if ((packetsize = getdec (&p)) < TFTP_DEFAULTSIZE_PACKET)
401
tp.opcode = htons (TFTP_ERROR);
402
tp.u.err.errcode = 8;
403
len = (grub_sprintf ((char *) tp.u.err.errmsg,
405
+ sizeof (tp.ip) + sizeof (tp.udp)
406
+ sizeof (tp.opcode) + sizeof (tp.u.err.errcode)
408
udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
409
iport, ntohs (tr->udp.src),
418
/* This ensures that the packet does not get processed as data! */
419
block = tp.u.ack.block = 0;
421
else if (tr->opcode == ntohs (TFTP_DATA))
423
len = ntohs (tr->udp.len) - sizeof (struct udphdr) - 4;
424
/* Shouldn't happen. */
425
if (len > packetsize)
429
block = ntohs (tp.u.ack.block = tr->u.data.block);
432
/* Neither TFTP_OACK nor TFTP_DATA. */
435
if ((block || bcounter) && (block != prevblock + 1))
436
/* Block order should be continuous */
437
tp.u.ack.block = htons (block = prevblock);
439
/* Should be continuous. */
440
tp.opcode = htons (TFTP_ACK);
441
oport = ntohs (tr->udp.src);
443
udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, iport,
444
oport, TFTP_MIN_PACKET, &tp);
446
if ((unsigned short) (block - prevblock) != 1)
447
/* Retransmission or OACK, don't process via callback
448
* and don't change the value of prevblock. */
452
/* Is it the right place to zero the timer? */
455
if ((rc = fnc (tr->u.data.download,
456
++bcounter, len, len < packetsize)) >= 0)
460
if (len < packetsize)
467
/**************************************************************************
468
RARP - Get my IP address and load information
469
**************************************************************************/
475
/* arp and rarp requests share the same packet structure. */
476
struct arprequest rarpreq;
478
/* Make sure that an ethernet is probed. */
482
/* Clear the ready flag. */
485
grub_memset (&rarpreq, 0, sizeof (rarpreq));
487
rarpreq.hwtype = htons (1);
488
rarpreq.protocol = htons (IP);
489
rarpreq.hwlen = ETH_ALEN;
490
rarpreq.protolen = 4;
491
rarpreq.opcode = htons (RARP_REQUEST);
492
grub_memmove ((char *) &rarpreq.shwaddr, arptable[ARP_CLIENT].node,
494
/* sipaddr is already zeroed out */
495
grub_memmove ((char *) &rarpreq.thwaddr, arptable[ARP_CLIENT].node,
497
/* tipaddr is already zeroed out */
499
for (retry = 0; retry < MAX_ARP_RETRIES; ++retry)
503
eth_transmit (broadcast, RARP, sizeof (rarpreq), &rarpreq);
505
timeout = rfc2131_sleep_interval (TIMEOUT, retry);
506
if (await_reply (AWAIT_RARP, 0, rarpreq.shwaddr, timeout))
513
if (retry < MAX_ARP_RETRIES)
522
/**************************************************************************
523
BOOTP - Get my IP address and load information
524
**************************************************************************/
529
#ifndef NO_DHCP_SUPPORT
531
#endif /* ! NO_DHCP_SUPPORT */
533
unsigned long starttime;
535
/* Make sure that an ethernet is probed. */
539
/* Clear the ready flag. */
543
grub_printf ("network is ready.\n");
546
grub_memset (&ip, 0, sizeof (struct bootpip_t));
547
ip.bp.bp_op = BOOTP_REQUEST;
549
ip.bp.bp_hlen = ETH_ALEN;
550
starttime = currticks ();
551
/* Use lower 32 bits of node address, more likely to be
552
distinct than the time since booting */
553
grub_memmove (&xid, &arptable[ARP_CLIENT].node[2], sizeof(xid));
554
ip.bp.bp_xid = xid += htonl (starttime);
555
grub_memmove (ip.bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
557
etherboot_printf ("bp_op = %d\n", ip.bp.bp_op);
558
etherboot_printf ("bp_htype = %d\n", ip.bp.bp_htype);
559
etherboot_printf ("bp_hlen = %d\n", ip.bp.bp_hlen);
560
etherboot_printf ("bp_xid = %d\n", ip.bp.bp_xid);
561
etherboot_printf ("bp_hwaddr = %!\n", ip.bp.bp_hwaddr);
562
etherboot_printf ("bp_hops = %d\n", (int) ip.bp.bp_hops);
563
etherboot_printf ("bp_secs = %d\n", (int) ip.bp.bp_hwaddr);
566
#ifdef NO_DHCP_SUPPORT
567
/* Request RFC-style options. */
568
grub_memmove (ip.bp.bp_vend, rfc1533_cookie, 5);
570
/* Request RFC-style options. */
571
grub_memmove (ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
572
grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie, dhcpdiscover,
573
sizeof dhcpdiscover);
574
grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcpdiscover,
575
rfc1533_end, sizeof rfc1533_end);
576
#endif /* ! NO_DHCP_SUPPORT */
578
for (retry = 0; retry < MAX_BOOTP_RETRIES;)
583
grub_printf ("retry = %d\n", retry);
586
/* Clear out the Rx queue first. It contains nothing of
587
* interest, except possibly ARP requests from the DHCP/TFTP
588
* server. We use polling throughout Etherboot, so some time
589
* may have passed since we last polled the receive queue,
590
* which may now be filled with broadcast packets. This will
591
* cause the reply to the packets we are about to send to be
592
* lost immediately. Not very clever. */
593
await_reply (AWAIT_QDRAIN, 0, NULL, 0);
595
udp_transmit (IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
596
sizeof (struct bootpip_t), &ip);
597
timeout = rfc2131_sleep_interval (TIMEOUT, retry++);
598
#ifdef NO_DHCP_SUPPORT
599
if (await_reply (AWAIT_BOOTP, 0, NULL, timeout))
604
#else /* ! NO_DHCP_SUPPORT */
605
if (await_reply (AWAIT_BOOTP, 0, NULL, timeout))
607
if (dhcp_reply != DHCPOFFER)
615
etherboot_printf ("bp_op = %d\n", (int) ip.bp.bp_op);
616
etherboot_printf ("bp_htype = %d\n", (int) ip.bp.bp_htype);
617
etherboot_printf ("bp_hlen = %d\n", (int) ip.bp.bp_hlen);
618
etherboot_printf ("bp_xid = %d\n", (int) ip.bp.bp_xid);
619
etherboot_printf ("bp_hwaddr = %!\n", ip.bp.bp_hwaddr);
620
etherboot_printf ("bp_hops = %d\n", (int) ip.bp.bp_hops);
621
etherboot_printf ("bp_secs = %d\n", (int) ip.bp.bp_hwaddr);
623
grub_memmove (ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
624
grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie,
625
dhcprequest, sizeof dhcprequest);
626
grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie
627
+ sizeof dhcprequest,
628
rfc1533_end, sizeof rfc1533_end);
629
grub_memmove (ip.bp.bp_vend + 9, (char *) &dhcp_server,
631
grub_memmove (ip.bp.bp_vend + 15, (char *) &dhcp_addr,
634
grub_printf ("errnum = %d\n", errnum);
636
for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES;)
640
grub_printf ("reqretry = %d\n", reqretry);
643
ret = udp_transmit (IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
644
sizeof (struct bootpip_t), &ip);
646
grub_printf ("udp_transmit failed.\n");
649
timeout = rfc2131_sleep_interval (TIMEOUT, reqretry++);
650
if (await_reply (AWAIT_BOOTP, 0, NULL, timeout))
651
if (dhcp_reply == DHCPACK)
658
grub_printf ("dhcp_reply = %d\n", dhcp_reply);
665
#endif /* ! NO_DHCP_SUPPORT */
670
ip.bp.bp_secs = htons ((currticks () - starttime) / TICKS_PER_SEC);
677
/**************************************************************************
678
UDPCHKSUM - Checksum UDP Packet (one of the rare cases when assembly is
680
RETURNS: checksum, 0 on checksum error. This
681
allows for using the same routine for RX and TX summing:
682
RX if (packet->udp.chksum && udpchksum(packet))
683
error("checksum error");
684
TX packet->udp.chksum=0;
685
if (0==(packet->udp.chksum=udpchksum(packet)))
686
packet->upd.chksum=0xffff;
687
**************************************************************************/
689
dosum (unsigned short *start, unsigned int len, unsigned short *sum)
694
"xchg %%al,%%ah\n\t" /* convert to host byte order */
695
"adcw %%ax,%0\n\t" /* add carry of previous iteration */
697
"adcw $0,%0" /* add carry of last iteration */
698
: "=b" (*sum), "=S"(start), "=c"(len)
699
: "0"(*sum), "1"(start), "2"(len)
705
* proto, src_ip, dst_ip, udp_dport, udp_sport, 2*udp_len, payload
707
static unsigned short
708
udpchksum (struct iphdr *packet)
710
int len = ntohs (packet->len);
713
/* add udplength + protocol number */
714
rval = (len - sizeof (struct iphdr)) + IP_UDP;
716
/* pad to an even number of bytes */
718
((char *) packet)[len++] = 0;
721
/* sum over src/dst ipaddr + udp packet */
722
len -= (char *) &packet->src - (char *) packet;
723
dosum ((unsigned short *) &packet->src, len >> 1, &rval);
725
/* take one's complement */
729
/**************************************************************************
730
AWAIT_REPLY - Wait until we get a response for our request
731
**************************************************************************/
733
await_reply (int type, int ival, void *ptr, int timeout)
738
struct arprequest *arpreply;
739
struct bootp_t *bootpreply;
740
unsigned short ptype;
741
unsigned int protohdrlen = (ETH_HLEN + sizeof (struct iphdr)
742
+ sizeof (struct udphdr));
744
/* Clear the abort flag. */
747
time = timeout + currticks ();
748
/* The timeout check is done below. The timeout is only checked if
749
* there is no packet in the Rx queue. This assumes that eth_poll()
750
* needs a negligible amount of time. */
755
/* We have something! */
757
/* Check for ARP - No IP hdr. */
758
if (nic.packetlen >= ETH_HLEN)
760
ptype = (((unsigned short) nic.packet[12]) << 8
761
| ((unsigned short) nic.packet[13]));
764
/* What else could we do with it? */
767
if (nic.packetlen >= ETH_HLEN + sizeof (struct arprequest)
772
arpreply = (struct arprequest *) &nic.packet[ETH_HLEN];
774
if (arpreply->opcode == htons (ARP_REPLY)
775
&& ! grub_memcmp (arpreply->sipaddr, ptr, sizeof (in_addr))
776
&& type == AWAIT_ARP)
778
grub_memmove ((char *) arptable[ival].node,
784
grub_memmove ((char *) &tmp, arpreply->tipaddr,
787
if (arpreply->opcode == htons (ARP_REQUEST)
788
&& tmp == arptable[ARP_CLIENT].ipaddr.s_addr)
790
arpreply->opcode = htons (ARP_REPLY);
791
grub_memmove (arpreply->tipaddr, arpreply->sipaddr,
793
grub_memmove (arpreply->thwaddr, (char *) arpreply->shwaddr,
795
grub_memmove (arpreply->sipaddr,
796
(char *) &arptable[ARP_CLIENT].ipaddr,
798
grub_memmove (arpreply->shwaddr,
799
arptable[ARP_CLIENT].node,
801
eth_transmit (arpreply->thwaddr, ARP,
802
sizeof (struct arprequest),
805
grub_memmove (&tmp, arpreply->tipaddr, sizeof (in_addr));
806
etherboot_printf ("Sent ARP reply to: %@\n", tmp);
813
if (type == AWAIT_QDRAIN)
816
/* Check for RARP - No IP hdr. */
817
if (type == AWAIT_RARP
818
&& nic.packetlen >= ETH_HLEN + sizeof (struct arprequest)
821
arpreply = (struct arprequest *) &nic.packet[ETH_HLEN];
823
if (arpreply->opcode == htons (RARP_REPLY)
824
&& ! grub_memcmp (arpreply->thwaddr, ptr, ETH_ALEN))
826
grub_memmove ((char *) arptable[ARP_SERVER].node,
827
arpreply->shwaddr, ETH_ALEN);
828
grub_memmove ((char *) &arptable[ARP_SERVER].ipaddr,
829
arpreply->sipaddr, sizeof (in_addr));
830
grub_memmove ((char *) &arptable[ARP_CLIENT].ipaddr,
831
arpreply->tipaddr, sizeof (in_addr));
838
/* Anything else has IP header. */
839
if (nic.packetlen < protohdrlen || ptype != IP)
842
ip = (struct iphdr *) &nic.packet[ETH_HLEN];
843
if (ip->verhdrlen != 0x45
844
|| ipchksum ((unsigned short *) ip, sizeof (struct iphdr))
845
|| ip->protocol != IP_UDP)
849
- Till Straumann <Till.Straumann@TU-Berlin.de>
850
added udp checksum (safer on a wireless link)
851
added fragmentation check: I had a corrupted image
852
in memory due to fragmented TFTP packets - took me
853
3 days to find the cause for this :-(
856
/* If More Fragments bit and Fragment Offset field
857
are non-zero then packet is fragmented */
858
if (ip->frags & htons(0x3FFF))
860
grub_printf ("ALERT: got a fragmented packet - reconfigure your server\n");
864
udp = (struct udphdr *) &nic.packet[(ETH_HLEN
865
+ sizeof (struct iphdr))];
866
if (udp->chksum && udpchksum (ip))
868
grub_printf ("UDP checksum error\n");
873
bootpreply = (struct bootp_t *)
874
&nic.packet[(ETH_HLEN + sizeof (struct iphdr)
875
+ sizeof (struct udphdr))];
876
if (type == AWAIT_BOOTP
877
#ifdef NO_DHCP_SUPPORT
878
&& (nic.packetlen >= (ETH_HLEN + sizeof (struct bootp_t)))
881
>= (ETH_HLEN + sizeof (struct bootp_t) - DHCP_OPT_LEN))
882
#endif /* ! NO_DHCP_SUPPORT */
883
&& udp->dest == htons (BOOTP_CLIENT)
884
&& bootpreply->bp_op == BOOTP_REPLY
885
&& bootpreply->bp_xid == xid
886
&& (! grub_memcmp (broadcast, bootpreply->bp_hwaddr, ETH_ALEN)
887
|| ! grub_memcmp (arptable[ARP_CLIENT].node,
888
bootpreply->bp_hwaddr, ETH_ALEN)))
891
grub_printf ("BOOTP packet was received.\n");
893
arptable[ARP_CLIENT].ipaddr.s_addr
894
= bootpreply->bp_yiaddr.s_addr;
895
#ifndef NO_DHCP_SUPPORT
896
dhcp_addr.s_addr = bootpreply->bp_yiaddr.s_addr;
898
etherboot_printf ("dhcp_addr = %@\n", dhcp_addr.s_addr);
900
#endif /* ! NO_DHCP_SUPPORT */
901
netmask = default_netmask ();
902
arptable[ARP_SERVER].ipaddr.s_addr
903
= bootpreply->bp_siaddr.s_addr;
905
grub_memset (arptable[ARP_SERVER].node, 0, ETH_ALEN);
906
arptable[ARP_GATEWAY].ipaddr.s_addr
907
= bootpreply->bp_giaddr.s_addr;
909
grub_memset (arptable[ARP_GATEWAY].node, 0, ETH_ALEN);
911
grub_memmove ((char *) BOOTP_DATA_ADDR, (char *) bootpreply,
912
sizeof (struct bootpd_t));
913
#ifdef NO_DHCP_SUPPORT
914
decode_rfc1533 (BOOTP_DATA_ADDR->bootp_reply.bp_vend,
915
0, BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN, 1);
917
decode_rfc1533 (BOOTP_DATA_ADDR->bootp_reply.bp_vend,
918
0, DHCP_OPT_LEN + MAX_BOOTP_EXTLEN, 1);
919
#endif /* ! NO_DHCP_SUPPORT */
925
if (type == AWAIT_TFTP && ntohs (udp->dest) == ival)
930
/* Check for abort key only if the Rx queue is empty -
931
* as long as we have something to process, don't
932
* assume that something failed. It is unlikely that
933
* we have no processing time left between packets. */
934
if (checkkey () != -1 && ASCII_CHAR (getkey ()) == CTRL_C)
940
/* Do the timeout after at least a full queue walk. */
941
if ((timeout == 0) || (currticks() > time))
951
/**************************************************************************
952
DECODE_RFC1533 - Decodes RFC1533 header
953
**************************************************************************/
955
decode_rfc1533 (unsigned char *p, int block, int len, int eof)
957
static unsigned char *extdata = NULL, *extend = NULL;
958
unsigned char *extpath = NULL;
963
end_of_rfc1533 = NULL;
964
vendorext_isvalid = 0;
966
if (grub_memcmp (p, rfc1533_cookie, 4))
967
/* no RFC 1533 header found */
977
if (grub_memcmp (p, rfc1533_cookie, 4))
978
/* no RFC 1533 header found */
986
<= ((unsigned char *)
987
&(BOOTP_DATA_ADDR->bootp_extension[MAX_BOOTP_EXTLEN])))
989
grub_memmove (extend, p, len);
994
grub_printf ("Overflow in vendor data buffer! Aborting...\n");
995
*extdata = RFC1533_END;
1008
unsigned char c = *p;
1010
if (c == RFC1533_PAD)
1015
else if (c == RFC1533_END)
1017
end_of_rfc1533 = endp = p;
1020
else if (c == RFC1533_NETMASK)
1022
grub_memmove ((char *) &netmask, p + 2, sizeof (in_addr));
1024
else if (c == RFC1533_GATEWAY)
1026
/* This is a little simplistic, but it will
1027
usually be sufficient.
1028
Take only the first entry. */
1029
if (TAG_LEN (p) >= sizeof (in_addr))
1030
grub_memmove ((char *) &arptable[ARP_GATEWAY].ipaddr, p + 2,
1033
else if (c == RFC1533_EXTENSIONPATH)
1035
#ifndef NO_DHCP_SUPPORT
1036
else if (c == RFC2132_MSG_TYPE)
1038
dhcp_reply = *(p + 2);
1040
else if (c == RFC2132_SRV_ID)
1042
grub_memmove ((char *) &dhcp_server, p + 2, sizeof (in_addr));
1044
etherboot_printf ("dhcp_server = %@\n", dhcp_server.s_addr);
1047
#endif /* ! NO_DHCP_SUPPORT */
1048
else if (c == RFC1533_VENDOR_MAGIC
1050
&& ! grub_memcmp (p + 2, vendorext_magic, 4)
1051
&& p[6] == RFC1533_VENDOR_MAJOR)
1052
vendorext_isvalid++;
1053
/* GRUB now handles its own tag. Get the name of a configuration
1054
file from the network. Cool... */
1055
else if (c == RFC1533_VENDOR_CONFIGFILE)
1057
int l = TAG_LEN (p);
1059
/* Eliminate the trailing NULs according to RFC 2132. */
1060
while (*(p + 2 + l - 1) == '\000' && l > 0)
1063
/* XXX: Should check if LEN is less than the maximum length
1064
of CONFIG_FILE. This kind of robustness will be a goal
1066
grub_memmove (config_file, p + 2, l);
1070
p += TAG_LEN (p) + 2;
1073
extdata = extend = endp;
1075
/* Perhaps we can eliminate this because we doesn't require so
1076
much information, but I leave this alone. */
1077
if (block == 0 && extpath != NULL)
1080
int fnamelen = TAG_LEN (extpath);
1082
while (*(extpath + 2 + fnamelen - 1) == '\000' && fnamelen > 0)
1085
if (fnamelen + 1 > sizeof (fname))
1087
grub_printf ("Too long file name for Extensions Path\n");
1090
else if (! fnamelen)
1092
grub_printf ("Empty file name for Extensions Path\n");
1096
grub_memmove (fname, extpath + 2, fnamelen);
1097
fname[fnamelen] = '\000';
1098
grub_printf ("Loading BOOTP-extension file: %s\n", fname);
1099
tftp (fname, decode_rfc1533);
1102
/* Proceed with next block. */
1106
/**************************************************************************
1107
IPCHKSUM - Checksum IP Header
1108
**************************************************************************/
1109
static unsigned short
1110
ipchksum (unsigned short *ip, int len)
1112
unsigned long sum = 0;
1120
return (~sum) & 0x0000FFFF;
1123
#define TWO_SECOND_DIVISOR (2147483647l/TICKS_PER_SEC)
1125
/**************************************************************************
1126
RFC2131_SLEEP_INTERVAL - sleep for expotentially longer times
1127
**************************************************************************/
1129
rfc2131_sleep_interval (int base, int exp)
1131
static long seed = 0;
1135
#ifdef BACKOFF_LIMIT
1136
if (exp > BACKOFF_LIMIT)
1137
exp = BACKOFF_LIMIT;
1140
/* Initialize linear congruential generator */
1141
seed = (currticks () + *((long *) &arptable[ARP_CLIENT].node)
1142
+ ((short *) arptable[ARP_CLIENT].node)[2]);
1143
/* simplified version of the LCG given in Bruce Schneier's
1144
"Applied Cryptography" */
1146
if ((seed = 40014 * (seed - 53668 * q) - 12211 *q ) < 0)
1147
seed += 2147483563L;
1148
tmo = (base << exp) + (TICKS_PER_SEC - (seed / TWO_SECOND_DIVISOR));
1152
/**************************************************************************
1153
CLEANUP - shut down networking
1154
**************************************************************************/
1160
/* Stop receiving packets. */