2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2000,2001,2002 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 /* Clear out the ARP entry. */
172 grub_memset (arptable
[ARP_GATEWAY
].node
, 0, ETH_ALEN
);
174 if (svr
&& ! inet_aton (svr
, &arptable
[ARP_SERVER
].ipaddr
))
178 grub_memset (arptable
[ARP_SERVER
].node
, 0, ETH_ALEN
);
182 if (IP_BROADCAST
== (netmask
| arptable
[ARP_CLIENT
].ipaddr
.s_addr
)
183 || netmask
== (netmask
| arptable
[ARP_CLIENT
].ipaddr
.s_addr
)
194 /**************************************************************************
195 UDP_TRANSMIT - Send a UDP datagram
196 **************************************************************************/
198 udp_transmit (unsigned long destip
, unsigned int srcsock
,
199 unsigned int destsock
, int len
, const void *buf
)
203 struct arprequest arpreq
;
207 ip
= (struct iphdr
*) buf
;
208 udp
= (struct udphdr
*) ((unsigned long) buf
+ sizeof (struct iphdr
));
209 ip
->verhdrlen
= 0x45;
211 ip
->len
= htons (len
);
215 ip
->protocol
= IP_UDP
;
217 ip
->src
.s_addr
= arptable
[ARP_CLIENT
].ipaddr
.s_addr
;
218 ip
->dest
.s_addr
= destip
;
219 ip
->chksum
= ipchksum ((unsigned short *) buf
, sizeof (struct iphdr
));
220 udp
->src
= htons (srcsock
);
221 udp
->dest
= htons (destsock
);
222 udp
->len
= htons (len
- sizeof (struct iphdr
));
224 udp
->chksum
= htons (udpchksum (ip
));
226 if (udp
->chksum
== 0)
227 udp
->chksum
= 0xffff;
229 if (destip
== IP_BROADCAST
)
231 eth_transmit (broadcast
, IP
, len
, buf
);
235 if (((destip
& netmask
)
236 != (arptable
[ARP_CLIENT
].ipaddr
.s_addr
& netmask
))
237 && arptable
[ARP_GATEWAY
].ipaddr
.s_addr
)
238 destip
= arptable
[ARP_GATEWAY
].ipaddr
.s_addr
;
240 for (arpentry
= 0; arpentry
< MAX_ARP
; arpentry
++)
241 if (arptable
[arpentry
].ipaddr
.s_addr
== destip
)
244 if (arpentry
== MAX_ARP
)
246 etherboot_printf ("%@ is not in my arp table!\n", destip
);
250 for (i
= 0; i
< ETH_ALEN
; i
++)
251 if (arptable
[arpentry
].node
[i
])
256 /* Need to do arp request. */
258 grub_printf ("arp request.\n");
260 arpreq
.hwtype
= htons (1);
261 arpreq
.protocol
= htons (IP
);
262 arpreq
.hwlen
= ETH_ALEN
;
264 arpreq
.opcode
= htons (ARP_REQUEST
);
265 grub_memmove (arpreq
.shwaddr
, arptable
[ARP_CLIENT
].node
,
267 grub_memmove (arpreq
.sipaddr
, (char *) &arptable
[ARP_CLIENT
].ipaddr
,
269 grub_memset (arpreq
.thwaddr
, 0, ETH_ALEN
);
270 grub_memmove (arpreq
.tipaddr
, (char *) &destip
, sizeof (in_addr
));
272 for (retry
= 1; retry
<= MAX_ARP_RETRIES
; retry
++)
276 eth_transmit (broadcast
, ARP
, sizeof (arpreq
), &arpreq
);
277 timeout
= rfc2131_sleep_interval (TIMEOUT
, retry
);
279 if (await_reply (AWAIT_ARP
, arpentry
, arpreq
.tipaddr
, timeout
))
290 eth_transmit (arptable
[arpentry
].node
, IP
, len
, buf
);
296 /**************************************************************************
297 TFTP - Download extended BOOTP data, or kernel image
298 **************************************************************************/
300 tftp (const char *name
, int (*fnc
) (unsigned char *, int, int, int))
303 static unsigned short iport
= 2000;
304 unsigned short oport
= 0;
305 unsigned short len
, block
= 0, prevblock
= 0;
310 int packetsize
= TFTP_DEFAULTSIZE_PACKET
;
312 /* Clear out the Rx queue first. It contains nothing of interest,
313 * except possibly ARP requests from the DHCP/TFTP server. We use
314 * polling throughout Etherboot, so some time may have passed since we
315 * last polled the receive queue, which may now be filled with
316 * broadcast packets. This will cause the reply to the packets we are
317 * about to send to be lost immediately. Not very clever. */
318 await_reply (AWAIT_QDRAIN
, 0, NULL
, 0);
320 tp
.opcode
= htons (TFTP_RRQ
);
321 len
= (grub_sprintf ((char *) tp
.u
.rrq
, "%s%coctet%cblksize%c%d",
322 name
, 0, 0, 0, TFTP_MAX_PACKET
)
323 + sizeof (tp
.ip
) + sizeof (tp
.udp
) + sizeof (tp
.opcode
) + 1);
324 if (! udp_transmit (arptable
[ARP_SERVER
].ipaddr
.s_addr
, ++iport
,
325 TFTP_PORT
, len
, &tp
))
333 timeout
= rfc2131_sleep_interval (block
? TFTP_REXMT
: TIMEOUT
, retry
);
335 timeout
= rfc2131_sleep_interval (TIMEOUT
, retry
);
338 if (! await_reply (AWAIT_TFTP
, iport
, NULL
, timeout
))
340 if (! block
&& retry
++ < MAX_TFTP_RETRIES
)
342 /* Maybe initial request was lost. */
343 if (! udp_transmit (arptable
[ARP_SERVER
].ipaddr
.s_addr
,
344 ++iport
, TFTP_PORT
, len
, &tp
))
351 if (block
&& ((retry
+= TFTP_REXMT
) < TFTP_TIMEOUT
))
353 /* We resend our last ack. */
355 grub_printf ("<REXMT>\n");
357 udp_transmit (arptable
[ARP_SERVER
].ipaddr
.s_addr
,
359 TFTP_MIN_PACKET
, &tp
);
367 tr
= (struct tftp_t
*) &nic
.packet
[ETH_HLEN
];
368 if (tr
->opcode
== ntohs (TFTP_ERROR
))
370 grub_printf ("TFTP error %d (%s)\n",
371 ntohs (tr
->u
.err
.errcode
),
376 if (tr
->opcode
== ntohs (TFTP_OACK
))
378 char *p
= tr
->u
.oack
.data
, *e
;
380 /* Shouldn't happen. */
385 len
= ntohs (tr
->udp
.len
) - sizeof (struct udphdr
) - 2;
386 if (len
> TFTP_MAX_PACKET
)
390 while (*p
!= '\000' && p
< e
)
392 if (! grub_strcmp ("blksize", p
))
395 if ((packetsize
= getdec (&p
)) < TFTP_DEFAULTSIZE_PACKET
)
407 tp
.opcode
= htons (TFTP_ERROR
);
408 tp
.u
.err
.errcode
= 8;
409 len
= (grub_sprintf ((char *) tp
.u
.err
.errmsg
,
411 + sizeof (tp
.ip
) + sizeof (tp
.udp
)
412 + sizeof (tp
.opcode
) + sizeof (tp
.u
.err
.errcode
)
414 udp_transmit (arptable
[ARP_SERVER
].ipaddr
.s_addr
,
415 iport
, ntohs (tr
->udp
.src
),
424 /* This ensures that the packet does not get processed as data! */
425 block
= tp
.u
.ack
.block
= 0;
427 else if (tr
->opcode
== ntohs (TFTP_DATA
))
429 len
= ntohs (tr
->udp
.len
) - sizeof (struct udphdr
) - 4;
430 /* Shouldn't happen. */
431 if (len
> packetsize
)
435 block
= ntohs (tp
.u
.ack
.block
= tr
->u
.data
.block
);
438 /* Neither TFTP_OACK nor TFTP_DATA. */
441 if ((block
|| bcounter
) && (block
!= prevblock
+ 1))
442 /* Block order should be continuous */
443 tp
.u
.ack
.block
= htons (block
= prevblock
);
445 /* Should be continuous. */
446 tp
.opcode
= htons (TFTP_ACK
);
447 oport
= ntohs (tr
->udp
.src
);
449 udp_transmit (arptable
[ARP_SERVER
].ipaddr
.s_addr
, iport
,
450 oport
, TFTP_MIN_PACKET
, &tp
);
452 if ((unsigned short) (block
- prevblock
) != 1)
453 /* Retransmission or OACK, don't process via callback
454 * and don't change the value of prevblock. */
458 /* Is it the right place to zero the timer? */
461 if ((rc
= fnc (tr
->u
.data
.download
,
462 ++bcounter
, len
, len
< packetsize
)) >= 0)
466 if (len
< packetsize
)
473 /**************************************************************************
474 RARP - Get my IP address and load information
475 **************************************************************************/
481 /* arp and rarp requests share the same packet structure. */
482 struct arprequest rarpreq
;
484 /* Make sure that an ethernet is probed. */
488 /* Clear the ready flag. */
491 grub_memset (&rarpreq
, 0, sizeof (rarpreq
));
493 rarpreq
.hwtype
= htons (1);
494 rarpreq
.protocol
= htons (IP
);
495 rarpreq
.hwlen
= ETH_ALEN
;
496 rarpreq
.protolen
= 4;
497 rarpreq
.opcode
= htons (RARP_REQUEST
);
498 grub_memmove ((char *) &rarpreq
.shwaddr
, arptable
[ARP_CLIENT
].node
,
500 /* sipaddr is already zeroed out */
501 grub_memmove ((char *) &rarpreq
.thwaddr
, arptable
[ARP_CLIENT
].node
,
503 /* tipaddr is already zeroed out */
505 for (retry
= 0; retry
< MAX_ARP_RETRIES
; ++retry
)
509 eth_transmit (broadcast
, RARP
, sizeof (rarpreq
), &rarpreq
);
511 timeout
= rfc2131_sleep_interval (TIMEOUT
, retry
);
512 if (await_reply (AWAIT_RARP
, 0, rarpreq
.shwaddr
, timeout
))
519 if (retry
< MAX_ARP_RETRIES
)
528 /**************************************************************************
529 BOOTP - Get my IP address and load information
530 **************************************************************************/
535 #ifndef NO_DHCP_SUPPORT
537 #endif /* ! NO_DHCP_SUPPORT */
539 unsigned long starttime
;
541 /* Make sure that an ethernet is probed. */
545 /* Clear the ready flag. */
549 grub_printf ("network is ready.\n");
552 grub_memset (&ip
, 0, sizeof (struct bootpip_t
));
553 ip
.bp
.bp_op
= BOOTP_REQUEST
;
555 ip
.bp
.bp_hlen
= ETH_ALEN
;
556 starttime
= currticks ();
557 /* Use lower 32 bits of node address, more likely to be
558 distinct than the time since booting */
559 grub_memmove (&xid
, &arptable
[ARP_CLIENT
].node
[2], sizeof(xid
));
560 ip
.bp
.bp_xid
= xid
+= htonl (starttime
);
561 grub_memmove (ip
.bp
.bp_hwaddr
, arptable
[ARP_CLIENT
].node
, ETH_ALEN
);
563 etherboot_printf ("bp_op = %d\n", ip
.bp
.bp_op
);
564 etherboot_printf ("bp_htype = %d\n", ip
.bp
.bp_htype
);
565 etherboot_printf ("bp_hlen = %d\n", ip
.bp
.bp_hlen
);
566 etherboot_printf ("bp_xid = %d\n", ip
.bp
.bp_xid
);
567 etherboot_printf ("bp_hwaddr = %!\n", ip
.bp
.bp_hwaddr
);
568 etherboot_printf ("bp_hops = %d\n", (int) ip
.bp
.bp_hops
);
569 etherboot_printf ("bp_secs = %d\n", (int) ip
.bp
.bp_hwaddr
);
572 #ifdef NO_DHCP_SUPPORT
573 /* Request RFC-style options. */
574 grub_memmove (ip
.bp
.bp_vend
, rfc1533_cookie
, 5);
576 /* Request RFC-style options. */
577 grub_memmove (ip
.bp
.bp_vend
, rfc1533_cookie
, sizeof rfc1533_cookie
);
578 grub_memmove (ip
.bp
.bp_vend
+ sizeof rfc1533_cookie
, dhcpdiscover
,
579 sizeof dhcpdiscover
);
580 grub_memmove (ip
.bp
.bp_vend
+ sizeof rfc1533_cookie
+ sizeof dhcpdiscover
,
581 rfc1533_end
, sizeof rfc1533_end
);
582 #endif /* ! NO_DHCP_SUPPORT */
584 for (retry
= 0; retry
< MAX_BOOTP_RETRIES
;)
589 grub_printf ("retry = %d\n", retry
);
592 /* Clear out the Rx queue first. It contains nothing of
593 * interest, except possibly ARP requests from the DHCP/TFTP
594 * server. We use polling throughout Etherboot, so some time
595 * may have passed since we last polled the receive queue,
596 * which may now be filled with broadcast packets. This will
597 * cause the reply to the packets we are about to send to be
598 * lost immediately. Not very clever. */
599 await_reply (AWAIT_QDRAIN
, 0, NULL
, 0);
601 udp_transmit (IP_BROADCAST
, BOOTP_CLIENT
, BOOTP_SERVER
,
602 sizeof (struct bootpip_t
), &ip
);
603 timeout
= rfc2131_sleep_interval (TIMEOUT
, retry
++);
604 #ifdef NO_DHCP_SUPPORT
605 if (await_reply (AWAIT_BOOTP
, 0, NULL
, timeout
))
610 #else /* ! NO_DHCP_SUPPORT */
611 if (await_reply (AWAIT_BOOTP
, 0, NULL
, timeout
))
613 if (dhcp_reply
!= DHCPOFFER
)
621 etherboot_printf ("bp_op = %d\n", (int) ip
.bp
.bp_op
);
622 etherboot_printf ("bp_htype = %d\n", (int) ip
.bp
.bp_htype
);
623 etherboot_printf ("bp_hlen = %d\n", (int) ip
.bp
.bp_hlen
);
624 etherboot_printf ("bp_xid = %d\n", (int) ip
.bp
.bp_xid
);
625 etherboot_printf ("bp_hwaddr = %!\n", ip
.bp
.bp_hwaddr
);
626 etherboot_printf ("bp_hops = %d\n", (int) ip
.bp
.bp_hops
);
627 etherboot_printf ("bp_secs = %d\n", (int) ip
.bp
.bp_hwaddr
);
629 grub_memmove (ip
.bp
.bp_vend
, rfc1533_cookie
, sizeof rfc1533_cookie
);
630 grub_memmove (ip
.bp
.bp_vend
+ sizeof rfc1533_cookie
,
631 dhcprequest
, sizeof dhcprequest
);
632 grub_memmove (ip
.bp
.bp_vend
+ sizeof rfc1533_cookie
633 + sizeof dhcprequest
,
634 rfc1533_end
, sizeof rfc1533_end
);
635 grub_memmove (ip
.bp
.bp_vend
+ 9, (char *) &dhcp_server
,
637 grub_memmove (ip
.bp
.bp_vend
+ 15, (char *) &dhcp_addr
,
640 grub_printf ("errnum = %d\n", errnum
);
642 for (reqretry
= 0; reqretry
< MAX_BOOTP_RETRIES
;)
646 grub_printf ("reqretry = %d\n", reqretry
);
649 ret
= udp_transmit (IP_BROADCAST
, BOOTP_CLIENT
, BOOTP_SERVER
,
650 sizeof (struct bootpip_t
), &ip
);
652 grub_printf ("udp_transmit failed.\n");
655 timeout
= rfc2131_sleep_interval (TIMEOUT
, reqretry
++);
656 if (await_reply (AWAIT_BOOTP
, 0, NULL
, timeout
))
657 if (dhcp_reply
== DHCPACK
)
664 grub_printf ("dhcp_reply = %d\n", dhcp_reply
);
671 #endif /* ! NO_DHCP_SUPPORT */
676 ip
.bp
.bp_secs
= htons ((currticks () - starttime
) / TICKS_PER_SEC
);
683 /**************************************************************************
684 UDPCHKSUM - Checksum UDP Packet (one of the rare cases when assembly is
686 RETURNS: checksum, 0 on checksum error. This
687 allows for using the same routine for RX and TX summing:
688 RX if (packet->udp.chksum && udpchksum(packet))
689 error("checksum error");
690 TX packet->udp.chksum=0;
691 if (0==(packet->udp.chksum=udpchksum(packet)))
692 packet->upd.chksum=0xffff;
693 **************************************************************************/
695 dosum (unsigned short *start
, unsigned int len
, unsigned short *sum
)
700 "xchg %%al,%%ah\n\t" /* convert to host byte order */
701 "adcw %%ax,%0\n\t" /* add carry of previous iteration */
703 "adcw $0,%0" /* add carry of last iteration */
704 : "=b" (*sum
), "=S"(start
), "=c"(len
)
705 : "0"(*sum
), "1"(start
), "2"(len
)
711 * proto, src_ip, dst_ip, udp_dport, udp_sport, 2*udp_len, payload
713 static unsigned short
714 udpchksum (struct iphdr
*packet
)
716 int len
= ntohs (packet
->len
);
719 /* add udplength + protocol number */
720 rval
= (len
- sizeof (struct iphdr
)) + IP_UDP
;
722 /* pad to an even number of bytes */
724 ((char *) packet
)[len
++] = 0;
727 /* sum over src/dst ipaddr + udp packet */
728 len
-= (char *) &packet
->src
- (char *) packet
;
729 dosum ((unsigned short *) &packet
->src
, len
>> 1, &rval
);
731 /* take one's complement */
735 /**************************************************************************
736 AWAIT_REPLY - Wait until we get a response for our request
737 **************************************************************************/
739 await_reply (int type
, int ival
, void *ptr
, int timeout
)
744 struct arprequest
*arpreply
;
745 struct bootp_t
*bootpreply
;
746 unsigned short ptype
;
747 unsigned int protohdrlen
= (ETH_HLEN
+ sizeof (struct iphdr
)
748 + sizeof (struct udphdr
));
750 /* Clear the abort flag. */
753 time
= timeout
+ currticks ();
754 /* The timeout check is done below. The timeout is only checked if
755 * there is no packet in the Rx queue. This assumes that eth_poll()
756 * needs a negligible amount of time. */
761 /* We have something! */
763 /* Check for ARP - No IP hdr. */
764 if (nic
.packetlen
>= ETH_HLEN
)
766 ptype
= (((unsigned short) nic
.packet
[12]) << 8
767 | ((unsigned short) nic
.packet
[13]));
770 /* What else could we do with it? */
773 if (nic
.packetlen
>= ETH_HLEN
+ sizeof (struct arprequest
)
778 arpreply
= (struct arprequest
*) &nic
.packet
[ETH_HLEN
];
780 if (arpreply
->opcode
== htons (ARP_REPLY
)
781 && ! grub_memcmp (arpreply
->sipaddr
, ptr
, sizeof (in_addr
))
782 && type
== AWAIT_ARP
)
784 grub_memmove ((char *) arptable
[ival
].node
,
790 grub_memmove ((char *) &tmp
, arpreply
->tipaddr
,
793 if (arpreply
->opcode
== htons (ARP_REQUEST
)
794 && tmp
== arptable
[ARP_CLIENT
].ipaddr
.s_addr
)
796 arpreply
->opcode
= htons (ARP_REPLY
);
797 grub_memmove (arpreply
->tipaddr
, arpreply
->sipaddr
,
799 grub_memmove (arpreply
->thwaddr
, (char *) arpreply
->shwaddr
,
801 grub_memmove (arpreply
->sipaddr
,
802 (char *) &arptable
[ARP_CLIENT
].ipaddr
,
804 grub_memmove (arpreply
->shwaddr
,
805 arptable
[ARP_CLIENT
].node
,
807 eth_transmit (arpreply
->thwaddr
, ARP
,
808 sizeof (struct arprequest
),
811 grub_memmove (&tmp
, arpreply
->tipaddr
, sizeof (in_addr
));
812 etherboot_printf ("Sent ARP reply to: %@\n", tmp
);
819 if (type
== AWAIT_QDRAIN
)
822 /* Check for RARP - No IP hdr. */
823 if (type
== AWAIT_RARP
824 && nic
.packetlen
>= ETH_HLEN
+ sizeof (struct arprequest
)
827 arpreply
= (struct arprequest
*) &nic
.packet
[ETH_HLEN
];
829 if (arpreply
->opcode
== htons (RARP_REPLY
)
830 && ! grub_memcmp (arpreply
->thwaddr
, ptr
, ETH_ALEN
))
832 grub_memmove ((char *) arptable
[ARP_SERVER
].node
,
833 arpreply
->shwaddr
, ETH_ALEN
);
834 grub_memmove ((char *) &arptable
[ARP_SERVER
].ipaddr
,
835 arpreply
->sipaddr
, sizeof (in_addr
));
836 grub_memmove ((char *) &arptable
[ARP_CLIENT
].ipaddr
,
837 arpreply
->tipaddr
, sizeof (in_addr
));
844 /* Anything else has IP header. */
845 if (nic
.packetlen
< protohdrlen
|| ptype
!= IP
)
848 ip
= (struct iphdr
*) &nic
.packet
[ETH_HLEN
];
849 if (ip
->verhdrlen
!= 0x45
850 || ipchksum ((unsigned short *) ip
, sizeof (struct iphdr
))
851 || ip
->protocol
!= IP_UDP
)
855 - Till Straumann <Till.Straumann@TU-Berlin.de>
856 added udp checksum (safer on a wireless link)
857 added fragmentation check: I had a corrupted image
858 in memory due to fragmented TFTP packets - took me
859 3 days to find the cause for this :-(
862 /* If More Fragments bit and Fragment Offset field
863 are non-zero then packet is fragmented */
864 if (ip
->frags
& htons(0x3FFF))
866 grub_printf ("ALERT: got a fragmented packet - reconfigure your server\n");
870 udp
= (struct udphdr
*) &nic
.packet
[(ETH_HLEN
871 + sizeof (struct iphdr
))];
872 if (udp
->chksum
&& udpchksum (ip
))
874 grub_printf ("UDP checksum error\n");
879 bootpreply
= (struct bootp_t
*)
880 &nic
.packet
[(ETH_HLEN
+ sizeof (struct iphdr
)
881 + sizeof (struct udphdr
))];
882 if (type
== AWAIT_BOOTP
883 #ifdef NO_DHCP_SUPPORT
885 >= (ETH_HLEN
+ sizeof (struct bootp_t
) - BOOTP_VENDOR_LEN
))
888 >= (ETH_HLEN
+ sizeof (struct bootp_t
) - DHCP_OPT_LEN
))
889 #endif /* ! NO_DHCP_SUPPORT */
890 && udp
->dest
== htons (BOOTP_CLIENT
)
891 && bootpreply
->bp_op
== BOOTP_REPLY
892 && bootpreply
->bp_xid
== xid
893 && (! grub_memcmp (broadcast
, bootpreply
->bp_hwaddr
, ETH_ALEN
)
894 || ! grub_memcmp (arptable
[ARP_CLIENT
].node
,
895 bootpreply
->bp_hwaddr
, ETH_ALEN
)))
898 grub_printf ("BOOTP packet was received.\n");
900 arptable
[ARP_CLIENT
].ipaddr
.s_addr
901 = bootpreply
->bp_yiaddr
.s_addr
;
902 #ifndef NO_DHCP_SUPPORT
903 dhcp_addr
.s_addr
= bootpreply
->bp_yiaddr
.s_addr
;
905 etherboot_printf ("dhcp_addr = %@\n", dhcp_addr
.s_addr
);
907 #endif /* ! NO_DHCP_SUPPORT */
908 netmask
= default_netmask ();
909 arptable
[ARP_SERVER
].ipaddr
.s_addr
910 = bootpreply
->bp_siaddr
.s_addr
;
912 grub_memset (arptable
[ARP_SERVER
].node
, 0, ETH_ALEN
);
913 arptable
[ARP_GATEWAY
].ipaddr
.s_addr
914 = bootpreply
->bp_giaddr
.s_addr
;
916 grub_memset (arptable
[ARP_GATEWAY
].node
, 0, ETH_ALEN
);
918 grub_memmove ((char *) BOOTP_DATA_ADDR
, (char *) bootpreply
,
919 sizeof (struct bootpd_t
));
920 #ifdef NO_DHCP_SUPPORT
921 decode_rfc1533 (BOOTP_DATA_ADDR
->bootp_reply
.bp_vend
,
922 0, BOOTP_VENDOR_LEN
+ MAX_BOOTP_EXTLEN
, 1);
924 decode_rfc1533 (BOOTP_DATA_ADDR
->bootp_reply
.bp_vend
,
925 0, DHCP_OPT_LEN
+ MAX_BOOTP_EXTLEN
, 1);
926 #endif /* ! NO_DHCP_SUPPORT */
932 if (type
== AWAIT_TFTP
&& ntohs (udp
->dest
) == ival
)
937 /* Check for abort key only if the Rx queue is empty -
938 * as long as we have something to process, don't
939 * assume that something failed. It is unlikely that
940 * we have no processing time left between packets. */
941 if (checkkey () != -1 && ASCII_CHAR (getkey ()) == CTRL_C
)
947 /* Do the timeout after at least a full queue walk. */
948 if ((timeout
== 0) || (currticks() > time
))
958 /**************************************************************************
959 DECODE_RFC1533 - Decodes RFC1533 header
960 **************************************************************************/
962 decode_rfc1533 (unsigned char *p
, int block
, int len
, int eof
)
964 static unsigned char *extdata
= NULL
, *extend
= NULL
;
965 unsigned char *extpath
= NULL
;
970 end_of_rfc1533
= NULL
;
971 vendorext_isvalid
= 0;
973 if (grub_memcmp (p
, rfc1533_cookie
, 4))
974 /* no RFC 1533 header found */
984 if (grub_memcmp (p
, rfc1533_cookie
, 4))
985 /* no RFC 1533 header found */
993 <= ((unsigned char *)
994 &(BOOTP_DATA_ADDR
->bootp_extension
[MAX_BOOTP_EXTLEN
])))
996 grub_memmove (extend
, p
, len
);
1001 grub_printf ("Overflow in vendor data buffer! Aborting...\n");
1002 *extdata
= RFC1533_END
;
1015 unsigned char c
= *p
;
1017 if (c
== RFC1533_PAD
)
1022 else if (c
== RFC1533_END
)
1024 end_of_rfc1533
= endp
= p
;
1027 else if (c
== RFC1533_NETMASK
)
1029 grub_memmove ((char *) &netmask
, p
+ 2, sizeof (in_addr
));
1031 else if (c
== RFC1533_GATEWAY
)
1033 /* This is a little simplistic, but it will
1034 usually be sufficient.
1035 Take only the first entry. */
1036 if (TAG_LEN (p
) >= sizeof (in_addr
))
1037 grub_memmove ((char *) &arptable
[ARP_GATEWAY
].ipaddr
, p
+ 2,
1040 else if (c
== RFC1533_EXTENSIONPATH
)
1042 #ifndef NO_DHCP_SUPPORT
1043 else if (c
== RFC2132_MSG_TYPE
)
1045 dhcp_reply
= *(p
+ 2);
1047 else if (c
== RFC2132_SRV_ID
)
1049 grub_memmove ((char *) &dhcp_server
, p
+ 2, sizeof (in_addr
));
1051 etherboot_printf ("dhcp_server = %@\n", dhcp_server
.s_addr
);
1054 #endif /* ! NO_DHCP_SUPPORT */
1055 else if (c
== RFC1533_VENDOR_MAGIC
1057 && ! grub_memcmp (p
+ 2, vendorext_magic
, 4)
1058 && p
[6] == RFC1533_VENDOR_MAJOR
)
1059 vendorext_isvalid
++;
1060 /* GRUB now handles its own tag. Get the name of a configuration
1061 file from the network. Cool... */
1062 else if (c
== RFC1533_VENDOR_CONFIGFILE
)
1064 int l
= TAG_LEN (p
);
1066 /* Eliminate the trailing NULs according to RFC 2132. */
1067 while (*(p
+ 2 + l
- 1) == '\000' && l
> 0)
1070 /* XXX: Should check if LEN is less than the maximum length
1071 of CONFIG_FILE. This kind of robustness will be a goal
1073 grub_memmove (config_file
, p
+ 2, l
);
1077 p
+= TAG_LEN (p
) + 2;
1080 extdata
= extend
= endp
;
1082 /* Perhaps we can eliminate this because we doesn't require so
1083 much information, but I leave this alone. */
1084 if (block
== 0 && extpath
!= NULL
)
1087 int fnamelen
= TAG_LEN (extpath
);
1089 while (*(extpath
+ 2 + fnamelen
- 1) == '\000' && fnamelen
> 0)
1092 if (fnamelen
+ 1 > sizeof (fname
))
1094 grub_printf ("Too long file name for Extensions Path\n");
1097 else if (! fnamelen
)
1099 grub_printf ("Empty file name for Extensions Path\n");
1103 grub_memmove (fname
, extpath
+ 2, fnamelen
);
1104 fname
[fnamelen
] = '\000';
1105 grub_printf ("Loading BOOTP-extension file: %s\n", fname
);
1106 tftp (fname
, decode_rfc1533
);
1109 /* Proceed with next block. */
1113 /**************************************************************************
1114 IPCHKSUM - Checksum IP Header
1115 **************************************************************************/
1116 static unsigned short
1117 ipchksum (unsigned short *ip
, int len
)
1119 unsigned long sum
= 0;
1127 return (~sum
) & 0x0000FFFF;
1130 #define TWO_SECOND_DIVISOR (2147483647l/TICKS_PER_SEC)
1132 /**************************************************************************
1133 RFC2131_SLEEP_INTERVAL - sleep for expotentially longer times
1134 **************************************************************************/
1136 rfc2131_sleep_interval (int base
, int exp
)
1138 static long seed
= 0;
1142 #ifdef BACKOFF_LIMIT
1143 if (exp
> BACKOFF_LIMIT
)
1144 exp
= BACKOFF_LIMIT
;
1147 /* Initialize linear congruential generator */
1148 seed
= (currticks () + *((long *) &arptable
[ARP_CLIENT
].node
)
1149 + ((short *) arptable
[ARP_CLIENT
].node
)[2]);
1150 /* simplified version of the LCG given in Bruce Schneier's
1151 "Applied Cryptography" */
1153 if ((seed
= 40014 * (seed
- 53668 * q
) - 12211 *q
) < 0)
1154 seed
+= 2147483563L;
1155 tmo
= (base
<< exp
) + (TICKS_PER_SEC
- (seed
/ TWO_SECOND_DIVISOR
));
1159 /**************************************************************************
1160 CLEANUP - shut down networking
1161 **************************************************************************/
1167 /* Stop receiving packets. */