Home | History | Annotate | Download | only in netboot
      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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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 (at) 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
    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
   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
   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
   1163 cleanup_net (void)
   1164 {
   1165   if (network_ready)
   1166     {
   1167       /* Stop receiving packets.  */
   1168       eth_disable ();
   1169       network_ready = 0;
   1170     }
   1171 }
   1172