• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  GRUB  --  GRand Unified Bootloader
3  *  Copyright (C) 2000,2001,2002  Free Software Foundation, Inc.
4  *
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.
9  *
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.
14  *
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.
18  */
19 
20 /* Based on "src/main.c" in etherboot-5.0.5.  */
21 
22 /**************************************************************************
23 ETHERBOOT -  BOOTP/TFTP Bootstrap Program
24 
25 Author: Martin Renters
26   Date: Dec/93
27 
28 Literature dealing with the network protocols:
29        ARP - RFC826
30        RARP - RFC903
31        UDP - RFC768
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)
37 
38 **************************************************************************/
39 
40 #define GRUB	1
41 #include <etherboot.h>
42 #include <nic.h>
43 
44 /* #define DEBUG	1 */
45 
46 struct arptable_t arptable[MAX_ARP];
47 
48 /* Set if the user pushes Control-C.  */
49 int ip_abort = 0;
50 /* Set if an ethernet card is probed and IP addresses are set.  */
51 int network_ready = 0;
52 
53 struct rom_info rom;
54 
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;
60 
61 #ifndef	NO_DHCP_SUPPORT
62 #endif /* NO_DHCP_SUPPORT */
63 
64 /* �Eth */
65 static unsigned char vendorext_magic[] = {0xE4, 0x45, 0x74, 0x68};
66 static const unsigned char broadcast[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
67 
68 #ifdef	NO_DHCP_SUPPORT
69 
70 static unsigned char rfc1533_cookie[5] = {RFC1533_COOKIE, RFC1533_END};
71 
72 #else /* ! NO_DHCP_SUPPORT */
73 
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};
79 
80 static const unsigned char dhcpdiscover[] =
81 {
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
87 };
88 
89 static const unsigned char dhcprequest[] =
90 {
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 */
97   RFC2132_PARAM_LIST,
98   /* 4 standard + 2 vendortags */
99   4 + 2,
100   /* Standard parameters */
101   RFC1533_NETMASK, RFC1533_GATEWAY,
102   RFC1533_HOSTNAME, RFC1533_EXTENSIONPATH,
103   /* Etherboot vendortags */
104   RFC1533_VENDOR_MAGIC,
105   RFC1533_VENDOR_CONFIGFILE,
106 };
107 
108 #endif /* ! NO_DHCP_SUPPORT */
109 
110 static unsigned short ipchksum (unsigned short *ip, int len);
111 static unsigned short udpchksum (struct iphdr *packet);
112 
113 void
print_network_configuration(void)114 print_network_configuration (void)
115 {
116   if (! eth_probe ())
117     grub_printf ("No ethernet card found.\n");
118   else if (! network_ready)
119     grub_printf ("Not initialized yet.\n");
120   else
121     {
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);
126     }
127 }
128 
129 
130 /**************************************************************************
131 DEFAULT_NETMASK - Return default netmask for IP address
132 **************************************************************************/
133 static inline unsigned long
default_netmask(void)134 default_netmask (void)
135 {
136   int net = ntohl (arptable[ARP_CLIENT].ipaddr.s_addr) >> 24;
137   if (net <= 127)
138     return (htonl (0xff000000));
139   else if (net < 192)
140     return (htonl (0xffff0000));
141   else
142     return (htonl (0xffffff00));
143 }
144 
145 /* ifconfig - configure network interface.  */
146 int
ifconfig(char * ip,char * sm,char * gw,char * svr)147 ifconfig (char *ip, char *sm, char *gw, char *svr)
148 {
149   in_addr tmp;
150 
151   if (sm)
152     {
153       if (! inet_aton (sm, &tmp))
154 	return 0;
155 
156       netmask = tmp.s_addr;
157     }
158 
159   if (ip)
160     {
161       if (! inet_aton (ip, &arptable[ARP_CLIENT].ipaddr))
162 	return 0;
163 
164       if (! netmask && ! sm)
165 	netmask = default_netmask ();
166     }
167 
168   if (gw && ! inet_aton (gw, &arptable[ARP_GATEWAY].ipaddr))
169     return 0;
170 
171   /* Clear out the ARP entry.  */
172   grub_memset (arptable[ARP_GATEWAY].node, 0, ETH_ALEN);
173 
174   if (svr && ! inet_aton (svr, &arptable[ARP_SERVER].ipaddr))
175     return 0;
176 
177   /* Likewise.  */
178   grub_memset (arptable[ARP_SERVER].node, 0, ETH_ALEN);
179 
180   if (ip || sm)
181     {
182       if (IP_BROADCAST == (netmask | arptable[ARP_CLIENT].ipaddr.s_addr)
183 	  || netmask == (netmask | arptable[ARP_CLIENT].ipaddr.s_addr)
184 	  || ! netmask)
185 	network_ready = 0;
186       else
187 	network_ready = 1;
188     }
189 
190   return 1;
191 }
192 
193 
194 /**************************************************************************
195 UDP_TRANSMIT - Send a UDP datagram
196 **************************************************************************/
197 int
udp_transmit(unsigned long destip,unsigned int srcsock,unsigned int destsock,int len,const void * buf)198 udp_transmit (unsigned long destip, unsigned int srcsock,
199 	      unsigned int destsock, int len, const void *buf)
200 {
201   struct iphdr *ip;
202   struct udphdr *udp;
203   struct arprequest arpreq;
204   int arpentry, i;
205   int retry;
206 
207   ip = (struct iphdr *) buf;
208   udp = (struct udphdr *) ((unsigned long) buf + sizeof (struct iphdr));
209   ip->verhdrlen = 0x45;
210   ip->service = 0;
211   ip->len = htons (len);
212   ip->ident = 0;
213   ip->frags = 0;
214   ip->ttl = 60;
215   ip->protocol = IP_UDP;
216   ip->chksum = 0;
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));
223   udp->chksum = 0;
224   udp->chksum = htons (udpchksum (ip));
225 
226   if (udp->chksum == 0)
227     udp->chksum = 0xffff;
228 
229   if (destip == IP_BROADCAST)
230     {
231       eth_transmit (broadcast, IP, len, buf);
232     }
233   else
234     {
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;
239 
240       for (arpentry = 0; arpentry < MAX_ARP; arpentry++)
241 	if (arptable[arpentry].ipaddr.s_addr == destip)
242 	  break;
243 
244       if (arpentry == MAX_ARP)
245 	{
246 	  etherboot_printf ("%@ is not in my arp table!\n", destip);
247 	  return 0;
248 	}
249 
250       for (i = 0; i < ETH_ALEN; i++)
251 	if (arptable[arpentry].node[i])
252 	  break;
253 
254       if (i == ETH_ALEN)
255 	{
256 	  /* Need to do arp request.  */
257 #ifdef DEBUG
258 	  grub_printf ("arp request.\n");
259 #endif
260 	  arpreq.hwtype = htons (1);
261 	  arpreq.protocol = htons (IP);
262 	  arpreq.hwlen = ETH_ALEN;
263 	  arpreq.protolen = 4;
264 	  arpreq.opcode = htons (ARP_REQUEST);
265 	  grub_memmove (arpreq.shwaddr, arptable[ARP_CLIENT].node,
266 			ETH_ALEN);
267 	  grub_memmove (arpreq.sipaddr, (char *) &arptable[ARP_CLIENT].ipaddr,
268 			sizeof (in_addr));
269 	  grub_memset (arpreq.thwaddr, 0, ETH_ALEN);
270 	  grub_memmove (arpreq.tipaddr, (char *) &destip, sizeof (in_addr));
271 
272 	  for (retry = 1; retry <= MAX_ARP_RETRIES; retry++)
273 	    {
274 	      long timeout;
275 
276 	      eth_transmit (broadcast, ARP, sizeof (arpreq), &arpreq);
277 	      timeout = rfc2131_sleep_interval (TIMEOUT, retry);
278 
279 	      if (await_reply (AWAIT_ARP, arpentry, arpreq.tipaddr, timeout))
280 		goto xmit;
281 
282 	      if (ip_abort)
283 		return 0;
284 	    }
285 
286 	  return 0;
287 	}
288 
289     xmit:
290       eth_transmit (arptable[arpentry].node, IP, len, buf);
291     }
292 
293   return 1;
294 }
295 
296 /**************************************************************************
297 TFTP - Download extended BOOTP data, or kernel image
298 **************************************************************************/
299 static int
tftp(const char * name,int (* fnc)(unsigned char *,int,int,int))300 tftp (const char *name, int (*fnc) (unsigned char *, int, int, int))
301 {
302   int retry = 0;
303   static unsigned short iport = 2000;
304   unsigned short oport = 0;
305   unsigned short len, block = 0, prevblock = 0;
306   int bcounter = 0;
307   struct tftp_t *tr;
308   struct tftpreq_t tp;
309   int rc;
310   int packetsize = TFTP_DEFAULTSIZE_PACKET;
311 
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);
319 
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))
326     return 0;
327 
328   for (;;)
329     {
330       long timeout;
331 
332 #ifdef CONGESTED
333       timeout = rfc2131_sleep_interval (block ? TFTP_REXMT : TIMEOUT, retry);
334 #else
335       timeout = rfc2131_sleep_interval (TIMEOUT, retry);
336 #endif
337 
338       if (! await_reply (AWAIT_TFTP, iport, NULL, timeout))
339 	{
340 	  if (! block && retry++ < MAX_TFTP_RETRIES)
341 	    {
342 	      /* Maybe initial request was lost.  */
343 	      if (! udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
344 				  ++iport, TFTP_PORT, len, &tp))
345 		return 0;
346 
347 	      continue;
348 	    }
349 
350 #ifdef CONGESTED
351 	  if (block && ((retry += TFTP_REXMT) < TFTP_TIMEOUT))
352 	    {
353 	      /* We resend our last ack.  */
354 #ifdef MDEBUG
355 	      grub_printf ("<REXMT>\n");
356 #endif
357 	      udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
358 			    iport, oport,
359 			    TFTP_MIN_PACKET, &tp);
360 	      continue;
361 	    }
362 #endif
363 	  /* Timeout.  */
364 	  break;
365 	}
366 
367       tr = (struct tftp_t *) &nic.packet[ETH_HLEN];
368       if (tr->opcode == ntohs (TFTP_ERROR))
369 	{
370 	  grub_printf ("TFTP error %d (%s)\n",
371 		       ntohs (tr->u.err.errcode),
372 		       tr->u.err.errmsg);
373 	  break;
374 	}
375 
376       if (tr->opcode == ntohs (TFTP_OACK))
377 	{
378 	  char *p = tr->u.oack.data, *e;
379 
380 	  /* Shouldn't happen.  */
381 	  if (prevblock)
382 	    /* Ignore it.  */
383 	    continue;
384 
385 	  len = ntohs (tr->udp.len) - sizeof (struct udphdr) - 2;
386 	  if (len > TFTP_MAX_PACKET)
387 	    goto noak;
388 
389 	  e = p + len;
390 	  while (*p != '\000' && p < e)
391 	    {
392 	      if (! grub_strcmp ("blksize", p))
393 		{
394 		  p += 8;
395 		  if ((packetsize = getdec (&p)) < TFTP_DEFAULTSIZE_PACKET)
396 		    goto noak;
397 
398 		  while (p < e && *p)
399 		    p++;
400 
401 		  if (p < e)
402 		    p++;
403 		}
404 	      else
405 		{
406 		noak:
407 		  tp.opcode = htons (TFTP_ERROR);
408 		  tp.u.err.errcode = 8;
409 		  len = (grub_sprintf ((char *) tp.u.err.errmsg,
410 				       "RFC1782 error")
411 			 + sizeof (tp.ip) + sizeof (tp.udp)
412 			 + sizeof (tp.opcode) + sizeof (tp.u.err.errcode)
413 			 + 1);
414 		  udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
415 				iport, ntohs (tr->udp.src),
416 				len, &tp);
417 		  return 0;
418 		}
419 	    }
420 
421 	  if (p > e)
422 	    goto noak;
423 
424 	  /* This ensures that the packet does not get processed as data!  */
425 	  block = tp.u.ack.block = 0;
426 	}
427       else if (tr->opcode == ntohs (TFTP_DATA))
428 	{
429 	  len = ntohs (tr->udp.len) - sizeof (struct udphdr) - 4;
430 	  /* Shouldn't happen.  */
431 	  if (len > packetsize)
432 	    /* Ignore it.  */
433 	    continue;
434 
435 	  block = ntohs (tp.u.ack.block = tr->u.data.block);
436 	}
437       else
438 	/* Neither TFTP_OACK nor TFTP_DATA.  */
439 	break;
440 
441       if ((block || bcounter) && (block != prevblock + 1))
442 	/* Block order should be continuous */
443 	tp.u.ack.block = htons (block = prevblock);
444 
445       /* Should be continuous.  */
446       tp.opcode = htons (TFTP_ACK);
447       oport = ntohs (tr->udp.src);
448       /* Ack.  */
449       udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, iport,
450 		    oport, TFTP_MIN_PACKET, &tp);
451 
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.  */
455 	continue;
456 
457       prevblock = block;
458       /* Is it the right place to zero the timer?  */
459       retry = 0;
460 
461       if ((rc = fnc (tr->u.data.download,
462 		     ++bcounter, len, len < packetsize)) >= 0)
463 	return rc;
464 
465       /* End of data.  */
466       if (len < packetsize)
467 	return 1;
468     }
469 
470   return 0;
471 }
472 
473 /**************************************************************************
474 RARP - Get my IP address and load information
475 **************************************************************************/
476 int
rarp(void)477 rarp (void)
478 {
479   int retry;
480 
481   /* arp and rarp requests share the same packet structure.  */
482   struct arprequest rarpreq;
483 
484   /* Make sure that an ethernet is probed.  */
485   if (! eth_probe ())
486     return 0;
487 
488   /* Clear the ready flag.  */
489   network_ready = 0;
490 
491   grub_memset (&rarpreq, 0, sizeof (rarpreq));
492 
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,
499 		ETH_ALEN);
500   /* sipaddr is already zeroed out */
501   grub_memmove ((char *) &rarpreq.thwaddr, arptable[ARP_CLIENT].node,
502 		ETH_ALEN);
503   /* tipaddr is already zeroed out */
504 
505   for (retry = 0; retry < MAX_ARP_RETRIES; ++retry)
506     {
507       long timeout;
508 
509       eth_transmit (broadcast, RARP, sizeof (rarpreq), &rarpreq);
510 
511       timeout = rfc2131_sleep_interval (TIMEOUT, retry);
512       if (await_reply (AWAIT_RARP, 0, rarpreq.shwaddr, timeout))
513 	break;
514 
515       if (ip_abort)
516 	return 0;
517     }
518 
519   if (retry < MAX_ARP_RETRIES)
520     {
521       network_ready = 1;
522       return 1;
523     }
524 
525   return 0;
526 }
527 
528 /**************************************************************************
529 BOOTP - Get my IP address and load information
530 **************************************************************************/
531 int
bootp(void)532 bootp (void)
533 {
534   int retry;
535 #ifndef	NO_DHCP_SUPPORT
536   int reqretry;
537 #endif /* ! NO_DHCP_SUPPORT */
538   struct bootpip_t ip;
539   unsigned long starttime;
540 
541   /* Make sure that an ethernet is probed.  */
542   if (! eth_probe ())
543     return 0;
544 
545   /* Clear the ready flag.  */
546   network_ready = 0;
547 
548 #ifdef DEBUG
549   grub_printf ("network is ready.\n");
550 #endif
551 
552   grub_memset (&ip, 0, sizeof (struct bootpip_t));
553   ip.bp.bp_op = BOOTP_REQUEST;
554   ip.bp.bp_htype = 1;
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);
562 #ifdef DEBUG
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);
570 #endif
571 
572 #ifdef	NO_DHCP_SUPPORT
573   /* Request RFC-style options.  */
574   grub_memmove (ip.bp.bp_vend, rfc1533_cookie, 5);
575 #else
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 */
583 
584   for (retry = 0; retry < MAX_BOOTP_RETRIES;)
585     {
586       long timeout;
587 
588 #ifdef DEBUG
589       grub_printf ("retry = %d\n", retry);
590 #endif
591 
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);
600 
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))
606 	{
607 	  network_ready = 1;
608 	  return 1;
609 	}
610 #else /* ! NO_DHCP_SUPPORT */
611       if (await_reply (AWAIT_BOOTP, 0, NULL, timeout))
612 	{
613 	  if (dhcp_reply != DHCPOFFER)
614 	    {
615 	      network_ready = 1;
616 	      return 1;
617 	    }
618 
619 	  dhcp_reply = 0;
620 #ifdef DEBUG
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);
628 #endif
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,
636 			sizeof (in_addr));
637 	  grub_memmove (ip.bp.bp_vend + 15, (char *) &dhcp_addr,
638 			sizeof (in_addr));
639 #ifdef DEBUG
640 	  grub_printf ("errnum = %d\n", errnum);
641 #endif
642 	  for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES;)
643 	    {
644 	      int ret;
645 #ifdef DEBUG
646 	      grub_printf ("reqretry = %d\n", reqretry);
647 #endif
648 
649 	      ret = udp_transmit (IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
650 				  sizeof (struct bootpip_t), &ip);
651 	      if (! ret)
652 		grub_printf ("udp_transmit failed.\n");
653 
654 	      dhcp_reply = 0;
655 	      timeout = rfc2131_sleep_interval (TIMEOUT, reqretry++);
656 	      if (await_reply (AWAIT_BOOTP, 0, NULL, timeout))
657 		if (dhcp_reply == DHCPACK)
658 		  {
659 		    network_ready = 1;
660 		    return 1;
661 		  }
662 
663 #ifdef DEBUG
664 	      grub_printf ("dhcp_reply = %d\n", dhcp_reply);
665 #endif
666 
667 	      if (ip_abort)
668 		return 0;
669 	    }
670 	}
671 #endif /* ! NO_DHCP_SUPPORT */
672 
673       if (ip_abort)
674 	return 0;
675 
676       ip.bp.bp_secs = htons ((currticks () - starttime) / TICKS_PER_SEC);
677     }
678 
679   /* Timeout.  */
680   return 0;
681 }
682 
683 /**************************************************************************
684 UDPCHKSUM - Checksum UDP Packet (one of the rare cases when assembly is
685             actually simpler...)
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 **************************************************************************/
694 static inline void
dosum(unsigned short * start,unsigned int len,unsigned short * sum)695 dosum (unsigned short *start, unsigned int len, unsigned short *sum)
696 {
697   __asm__ __volatile__
698     ("clc\n"
699      "1:\tlodsw\n\t"
700      "xchg %%al,%%ah\n\t"	/* convert to host byte order */
701      "adcw %%ax,%0\n\t"		/* add carry of previous iteration */
702      "loop 1b\n\t"
703      "adcw $0,%0"		/* add carry of last iteration */
704      : "=b" (*sum), "=S"(start), "=c"(len)
705      : "0"(*sum), "1"(start), "2"(len)
706      : "ax", "cc"
707      );
708 }
709 
710 /* UDP sum:
711  * proto, src_ip, dst_ip, udp_dport, udp_sport, 2*udp_len, payload
712  */
713 static unsigned short
udpchksum(struct iphdr * packet)714 udpchksum (struct iphdr *packet)
715 {
716   int len = ntohs (packet->len);
717   unsigned short rval;
718 
719   /* add udplength + protocol number */
720   rval = (len - sizeof (struct iphdr)) + IP_UDP;
721 
722   /* pad to an even number of bytes */
723   if (len % 2) {
724     ((char *) packet)[len++] = 0;
725   }
726 
727   /* sum over src/dst ipaddr + udp packet */
728   len -= (char *) &packet->src - (char *) packet;
729   dosum ((unsigned short *) &packet->src, len >> 1, &rval);
730 
731   /* take one's complement */
732   return ~rval;
733 }
734 
735 /**************************************************************************
736 AWAIT_REPLY - Wait until we get a response for our request
737 **************************************************************************/
738 int
await_reply(int type,int ival,void * ptr,int timeout)739 await_reply (int type, int ival, void *ptr, int timeout)
740 {
741   unsigned long time;
742   struct iphdr *ip;
743   struct udphdr *udp;
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));
749 
750   /* Clear the abort flag.  */
751   ip_abort = 0;
752 
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.  */
757   for (;;)
758     {
759       if (eth_poll ())
760 	{
761 	  /* We have something!  */
762 
763 	  /* Check for ARP - No IP hdr.  */
764 	  if (nic.packetlen >= ETH_HLEN)
765 	    {
766 	      ptype = (((unsigned short) nic.packet[12]) << 8
767 		       | ((unsigned short) nic.packet[13]));
768 	    }
769 	  else
770 	    /* What else could we do with it?  */
771 	    continue;
772 
773 	  if (nic.packetlen >= ETH_HLEN + sizeof (struct arprequest)
774 	      && ptype == ARP)
775 	    {
776 	      unsigned long tmp;
777 
778 	      arpreply = (struct arprequest *) &nic.packet[ETH_HLEN];
779 
780 	      if (arpreply->opcode == htons (ARP_REPLY)
781 		  && ! grub_memcmp (arpreply->sipaddr, ptr, sizeof (in_addr))
782 		  && type == AWAIT_ARP)
783 		{
784 		  grub_memmove ((char *) arptable[ival].node,
785 				arpreply->shwaddr,
786 				ETH_ALEN);
787 		  return 1;
788 		}
789 
790 	      grub_memmove ((char *) &tmp, arpreply->tipaddr,
791 			    sizeof (in_addr));
792 
793 	      if (arpreply->opcode == htons (ARP_REQUEST)
794 		  && tmp == arptable[ARP_CLIENT].ipaddr.s_addr)
795 		{
796 		  arpreply->opcode = htons (ARP_REPLY);
797 		  grub_memmove (arpreply->tipaddr, arpreply->sipaddr,
798 				sizeof (in_addr));
799 		  grub_memmove (arpreply->thwaddr, (char *) arpreply->shwaddr,
800 				ETH_ALEN);
801 		  grub_memmove (arpreply->sipaddr,
802 				(char *) &arptable[ARP_CLIENT].ipaddr,
803 				sizeof (in_addr));
804 		  grub_memmove (arpreply->shwaddr,
805 				arptable[ARP_CLIENT].node,
806 				ETH_ALEN);
807 		  eth_transmit (arpreply->thwaddr, ARP,
808 				sizeof (struct arprequest),
809 				arpreply);
810 #ifdef MDEBUG
811 		  grub_memmove (&tmp, arpreply->tipaddr, sizeof (in_addr));
812 		  etherboot_printf ("Sent ARP reply to: %@\n", tmp);
813 #endif	/* MDEBUG */
814 		}
815 
816 	      continue;
817 	    }
818 
819 	  if (type == AWAIT_QDRAIN)
820 	    continue;
821 
822 	  /* Check for RARP - No IP hdr.  */
823 	  if (type == AWAIT_RARP
824 	      && nic.packetlen >= ETH_HLEN + sizeof (struct arprequest)
825 	      && ptype == RARP)
826 	    {
827 	      arpreply = (struct arprequest *) &nic.packet[ETH_HLEN];
828 
829 	      if (arpreply->opcode == htons (RARP_REPLY)
830 		  && ! grub_memcmp (arpreply->thwaddr, ptr, ETH_ALEN))
831 		{
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));
838 		  return 1;
839 		}
840 
841 	      continue;
842 	    }
843 
844 	  /* Anything else has IP header.  */
845 	  if (nic.packetlen < protohdrlen || ptype != IP)
846 	    continue;
847 
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)
852 	    continue;
853 
854 	  /*
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 :-(
860 	  */
861 
862 	  /* If More Fragments bit and Fragment Offset field
863 	     are non-zero then packet is fragmented */
864 	  if (ip->frags & htons(0x3FFF))
865 	    {
866 	      grub_printf ("ALERT: got a fragmented packet - reconfigure your server\n");
867 	      continue;
868 	    }
869 
870 	  udp = (struct udphdr *) &nic.packet[(ETH_HLEN
871 					       + sizeof (struct iphdr))];
872 	  if (udp->chksum && udpchksum (ip))
873 	    {
874 	      grub_printf ("UDP checksum error\n");
875 	      continue;
876 	    }
877 
878 	  /* BOOTP ?  */
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
884 	      && (nic.packetlen
885 		  >= (ETH_HLEN + sizeof (struct bootp_t) - BOOTP_VENDOR_LEN))
886 #else
887 	      && (nic.packetlen
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)))
896 	    {
897 #ifdef DEBUG
898 	      grub_printf ("BOOTP packet was received.\n");
899 #endif
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;
904 #ifdef DEBUG
905 	      etherboot_printf ("dhcp_addr = %@\n", dhcp_addr.s_addr);
906 #endif
907 #endif /* ! NO_DHCP_SUPPORT */
908 	      netmask = default_netmask ();
909 	      arptable[ARP_SERVER].ipaddr.s_addr
910 		= bootpreply->bp_siaddr.s_addr;
911 	      /* Kill arp.  */
912 	      grub_memset (arptable[ARP_SERVER].node, 0, ETH_ALEN);
913 	      arptable[ARP_GATEWAY].ipaddr.s_addr
914 		= bootpreply->bp_giaddr.s_addr;
915 	      /* Kill arp.  */
916 	      grub_memset (arptable[ARP_GATEWAY].node, 0, ETH_ALEN);
917 
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);
923 #else
924 	      decode_rfc1533 (BOOTP_DATA_ADDR->bootp_reply.bp_vend,
925 			      0, DHCP_OPT_LEN + MAX_BOOTP_EXTLEN, 1);
926 #endif /* ! NO_DHCP_SUPPORT */
927 
928 	      return 1;
929 	    }
930 
931 	  /* TFTP ? */
932 	  if (type == AWAIT_TFTP && ntohs (udp->dest) == ival)
933 	    return 1;
934 	}
935       else
936 	{
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)
942 	    {
943 	      ip_abort = 1;
944 	      return 0;
945 	    }
946 
947 	  /* Do the timeout after at least a full queue walk.  */
948 	  if ((timeout == 0) || (currticks() > time))
949 	    {
950 	      break;
951 	    }
952 	}
953     }
954 
955   return 0;
956 }
957 
958 /**************************************************************************
959 DECODE_RFC1533 - Decodes RFC1533 header
960 **************************************************************************/
961 int
decode_rfc1533(unsigned char * p,int block,int len,int eof)962 decode_rfc1533 (unsigned char *p, int block, int len, int eof)
963 {
964   static unsigned char *extdata = NULL, *extend = NULL;
965   unsigned char *extpath = NULL;
966   unsigned char *endp;
967 
968   if (block == 0)
969     {
970       end_of_rfc1533 = NULL;
971       vendorext_isvalid = 0;
972 
973       if (grub_memcmp (p, rfc1533_cookie, 4))
974 	/* no RFC 1533 header found */
975 	return 0;
976 
977       p += 4;
978       endp = p + len;
979     }
980   else
981     {
982       if (block == 1)
983 	{
984 	  if (grub_memcmp (p, rfc1533_cookie, 4))
985 	    /* no RFC 1533 header found */
986 	    return 0;
987 
988 	  p += 4;
989 	  len -= 4;
990 	}
991 
992       if (extend + len
993 	  <= ((unsigned char *)
994 	      &(BOOTP_DATA_ADDR->bootp_extension[MAX_BOOTP_EXTLEN])))
995 	{
996 	  grub_memmove (extend, p, len);
997 	  extend += len;
998 	}
999       else
1000 	{
1001 	  grub_printf ("Overflow in vendor data buffer! Aborting...\n");
1002 	  *extdata = RFC1533_END;
1003 	  return 0;
1004 	}
1005 
1006       p = extdata;
1007       endp = extend;
1008     }
1009 
1010   if (! eof)
1011     return -1;
1012 
1013   while (p < endp)
1014     {
1015       unsigned char c = *p;
1016 
1017       if (c == RFC1533_PAD)
1018 	{
1019 	  p++;
1020 	  continue;
1021 	}
1022       else if (c == RFC1533_END)
1023 	{
1024 	  end_of_rfc1533 = endp = p;
1025 	  continue;
1026 	}
1027       else if (c == RFC1533_NETMASK)
1028 	{
1029 	  grub_memmove ((char *) &netmask, p + 2, sizeof (in_addr));
1030 	}
1031       else if (c == RFC1533_GATEWAY)
1032 	{
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,
1038 			  sizeof (in_addr));
1039 	}
1040       else if (c == RFC1533_EXTENSIONPATH)
1041 	extpath = p;
1042 #ifndef	NO_DHCP_SUPPORT
1043       else if (c == RFC2132_MSG_TYPE)
1044 	{
1045 	  dhcp_reply = *(p + 2);
1046 	}
1047       else if (c == RFC2132_SRV_ID)
1048 	{
1049 	  grub_memmove ((char *) &dhcp_server, p + 2, sizeof (in_addr));
1050 #ifdef DEBUG
1051 	  etherboot_printf ("dhcp_server = %@\n", dhcp_server.s_addr);
1052 #endif
1053 	}
1054 #endif /* ! NO_DHCP_SUPPORT */
1055       else if (c == RFC1533_VENDOR_MAGIC
1056 	       && TAG_LEN(p) >= 6
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)
1063 	{
1064 	  int l = TAG_LEN (p);
1065 
1066 	  /* Eliminate the trailing NULs according to RFC 2132.  */
1067 	  while (*(p + 2 + l - 1) == '\000' && l > 0)
1068 	    l--;
1069 
1070 	  /* XXX: Should check if LEN is less than the maximum length
1071 	     of CONFIG_FILE. This kind of robustness will be a goal
1072 	     in GRUB 1.0.  */
1073 	  grub_memmove (config_file, p + 2, l);
1074 	  config_file[l] = 0;
1075 	}
1076 
1077       p += TAG_LEN (p) + 2;
1078     }
1079 
1080   extdata = extend = endp;
1081 
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)
1085     {
1086       char fname[64];
1087       int fnamelen = TAG_LEN (extpath);
1088 
1089       while (*(extpath + 2 + fnamelen - 1) == '\000' && fnamelen > 0)
1090 	fnamelen--;
1091 
1092       if (fnamelen + 1 > sizeof (fname))
1093 	{
1094 	  grub_printf ("Too long file name for Extensions Path\n");
1095 	  return 0;
1096 	}
1097       else if (! fnamelen)
1098 	{
1099 	  grub_printf ("Empty file name for Extensions Path\n");
1100 	  return 0;
1101 	}
1102 
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);
1107     }
1108 
1109   /* Proceed with next block.  */
1110   return -1;
1111 }
1112 
1113 /**************************************************************************
1114 IPCHKSUM - Checksum IP Header
1115 **************************************************************************/
1116 static unsigned short
ipchksum(unsigned short * ip,int len)1117 ipchksum (unsigned short *ip, int len)
1118 {
1119   unsigned long sum = 0;
1120   len >>= 1;
1121   while (len--)
1122     {
1123       sum += *(ip++);
1124       if (sum > 0xFFFF)
1125 	sum -= 0xFFFF;
1126     }
1127   return (~sum) & 0x0000FFFF;
1128 }
1129 
1130 #define TWO_SECOND_DIVISOR (2147483647l/TICKS_PER_SEC)
1131 
1132 /**************************************************************************
1133 RFC2131_SLEEP_INTERVAL - sleep for expotentially longer times
1134 **************************************************************************/
1135 long
rfc2131_sleep_interval(int base,int exp)1136 rfc2131_sleep_interval (int base, int exp)
1137 {
1138   static long seed = 0;
1139   long q;
1140   unsigned long tmo;
1141 
1142 #ifdef BACKOFF_LIMIT
1143   if (exp > BACKOFF_LIMIT)
1144     exp = BACKOFF_LIMIT;
1145 #endif
1146   if (!seed)
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" */
1152   q = seed / 53668;
1153   if ((seed = 40014 * (seed - 53668 * q) - 12211 *q ) < 0)
1154     seed += 2147483563L;
1155   tmo = (base << exp) + (TICKS_PER_SEC - (seed / TWO_SECOND_DIVISOR));
1156   return tmo;
1157 }
1158 
1159 /**************************************************************************
1160 CLEANUP - shut down networking
1161 **************************************************************************/
1162 void
cleanup_net(void)1163 cleanup_net (void)
1164 {
1165   if (network_ready)
1166     {
1167       /* Stop receiving packets.  */
1168       eth_disable ();
1169       network_ready = 0;
1170     }
1171 }
1172