~ubuntu-branches/ubuntu/utopic/grub/utopic

« back to all changes in this revision

Viewing changes to netboot/main.c

  • Committer: Bazaar Package Importer
  • Author(s): Jason Thomas
  • Date: 2002-02-04 15:35:01 UTC
  • Revision ID: james.westby@ubuntu.com-20020204153501-neulkag77r3a2m0v
Tags: upstream-0.91
Import upstream version 0.91

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  GRUB  --  GRand Unified Bootloader
 
3
 *  Copyright (C) 2000, 2001  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
  if (svr && ! inet_aton (svr, &arptable[ARP_SERVER].ipaddr)) 
 
172
    return 0;
 
173
  
 
174
  if (ip || sm)
 
175
    {
 
176
      if (IP_BROADCAST == (netmask | arptable[ARP_CLIENT].ipaddr.s_addr)
 
177
          || netmask == (netmask | arptable[ARP_CLIENT].ipaddr.s_addr)
 
178
          || ! netmask)
 
179
        network_ready = 0;
 
180
      else
 
181
        network_ready = 1;
 
182
    }
 
183
  
 
184
  return 1;
 
185
}
 
186
 
 
187
 
 
188
/**************************************************************************
 
189
UDP_TRANSMIT - Send a UDP datagram
 
190
**************************************************************************/
 
191
int 
 
192
udp_transmit (unsigned long destip, unsigned int srcsock,
 
193
              unsigned int destsock, int len, const void *buf)
 
194
{
 
195
  struct iphdr *ip;
 
196
  struct udphdr *udp;
 
197
  struct arprequest arpreq;
 
198
  int arpentry, i;
 
199
  int retry;
 
200
 
 
201
  ip = (struct iphdr *) buf;
 
202
  udp = (struct udphdr *) ((unsigned long) buf + sizeof (struct iphdr));
 
203
  ip->verhdrlen = 0x45;
 
204
  ip->service = 0;
 
205
  ip->len = htons (len);
 
206
  ip->ident = 0;
 
207
  ip->frags = 0;
 
208
  ip->ttl = 60;
 
209
  ip->protocol = IP_UDP;
 
210
  ip->chksum = 0;
 
211
  ip->src.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr;
 
212
  ip->dest.s_addr = destip;
 
213
  ip->chksum = ipchksum ((unsigned short *) buf, sizeof (struct iphdr));
 
214
  udp->src = htons (srcsock);
 
215
  udp->dest = htons (destsock);
 
216
  udp->len = htons (len - sizeof (struct iphdr));
 
217
  udp->chksum = 0;
 
218
  udp->chksum = htons (udpchksum (ip));
 
219
 
 
220
  if (udp->chksum == 0)
 
221
    udp->chksum = 0xffff;
 
222
  
 
223
  if (destip == IP_BROADCAST)
 
224
    {
 
225
      eth_transmit (broadcast, IP, len, buf);
 
226
    }
 
227
  else
 
228
    {
 
229
      if (((destip & netmask)
 
230
           != (arptable[ARP_CLIENT].ipaddr.s_addr & netmask))
 
231
          && arptable[ARP_GATEWAY].ipaddr.s_addr)
 
232
        destip = arptable[ARP_GATEWAY].ipaddr.s_addr;
 
233
      
 
234
      for (arpentry = 0; arpentry < MAX_ARP; arpentry++)
 
235
        if (arptable[arpentry].ipaddr.s_addr == destip)
 
236
          break;
 
237
      
 
238
      if (arpentry == MAX_ARP)
 
239
        {
 
240
          etherboot_printf ("%@ is not in my arp table!\n", destip);
 
241
          return 0;
 
242
        }
 
243
      
 
244
      for (i = 0; i < ETH_ALEN; i++)
 
245
        if (arptable[arpentry].node[i])
 
246
          break;
 
247
      
 
248
      if (i == ETH_ALEN)
 
249
        {
 
250
          /* Need to do arp request.  */
 
251
#ifdef DEBUG
 
252
          grub_printf ("arp request.\n");
 
253
#endif
 
254
          arpreq.hwtype = htons (1);
 
255
          arpreq.protocol = htons (IP);
 
256
          arpreq.hwlen = ETH_ALEN;
 
257
          arpreq.protolen = 4;
 
258
          arpreq.opcode = htons (ARP_REQUEST);
 
259
          grub_memmove (arpreq.shwaddr, arptable[ARP_CLIENT].node,
 
260
                        ETH_ALEN);
 
261
          grub_memmove (arpreq.sipaddr, (char *) &arptable[ARP_CLIENT].ipaddr,
 
262
                        sizeof (in_addr));
 
263
          grub_memset (arpreq.thwaddr, 0, ETH_ALEN);
 
264
          grub_memmove (arpreq.tipaddr, (char *) &destip, sizeof (in_addr));
 
265
          
 
266
          for (retry = 1; retry <= MAX_ARP_RETRIES; retry++)
 
267
            {
 
268
              long timeout;
 
269
              
 
270
              eth_transmit (broadcast, ARP, sizeof (arpreq), &arpreq);
 
271
              timeout = rfc2131_sleep_interval (TIMEOUT, retry);
 
272
              
 
273
              if (await_reply (AWAIT_ARP, arpentry, arpreq.tipaddr, timeout))
 
274
                goto xmit;
 
275
 
 
276
              if (ip_abort)
 
277
                return 0;
 
278
            }
 
279
          
 
280
          return 0;
 
281
        }
 
282
      
 
283
    xmit:
 
284
      eth_transmit (arptable[arpentry].node, IP, len, buf);
 
285
    }
 
286
  
 
287
  return 1;
 
288
}
 
289
 
 
290
/**************************************************************************
 
291
TFTP - Download extended BOOTP data, or kernel image
 
292
**************************************************************************/
 
293
static int
 
294
tftp (const char *name, int (*fnc) (unsigned char *, int, int, int))
 
295
{
 
296
  int retry = 0;
 
297
  static unsigned short iport = 2000;
 
298
  unsigned short oport = 0;
 
299
  unsigned short len, block = 0, prevblock = 0;
 
300
  int bcounter = 0;
 
301
  struct tftp_t *tr;
 
302
  struct tftpreq_t tp;
 
303
  int rc;
 
304
  int packetsize = TFTP_DEFAULTSIZE_PACKET;
 
305
  
 
306
  /* Clear out the Rx queue first.  It contains nothing of interest,
 
307
   * except possibly ARP requests from the DHCP/TFTP server.  We use
 
308
   * polling throughout Etherboot, so some time may have passed since we
 
309
   * last polled the receive queue, which may now be filled with
 
310
   * broadcast packets.  This will cause the reply to the packets we are
 
311
   * about to send to be lost immediately.  Not very clever.  */
 
312
  await_reply (AWAIT_QDRAIN, 0, NULL, 0);
 
313
  
 
314
  tp.opcode = htons (TFTP_RRQ);
 
315
  len = (grub_sprintf ((char *) tp.u.rrq, "%s%coctet%cblksize%c%d",
 
316
                       name, 0, 0, 0, TFTP_MAX_PACKET)
 
317
         + sizeof (tp.ip) + sizeof (tp.udp) + sizeof (tp.opcode) + 1);
 
318
  if (! udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, ++iport,
 
319
                      TFTP_PORT, len, &tp))
 
320
    return 0;
 
321
  
 
322
  for (;;)
 
323
    {
 
324
      long timeout;
 
325
      
 
326
#ifdef CONGESTED
 
327
      timeout = rfc2131_sleep_interval (block ? TFTP_REXMT : TIMEOUT, retry);
 
328
#else
 
329
      timeout = rfc2131_sleep_interval (TIMEOUT, retry);
 
330
#endif
 
331
 
 
332
      if (! await_reply (AWAIT_TFTP, iport, NULL, timeout))
 
333
        {
 
334
          if (! block && retry++ < MAX_TFTP_RETRIES)
 
335
            {
 
336
              /* Maybe initial request was lost.  */
 
337
              if (! udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
 
338
                                  ++iport, TFTP_PORT, len, &tp))
 
339
                return 0;
 
340
              
 
341
              continue;
 
342
            }
 
343
          
 
344
#ifdef CONGESTED
 
345
          if (block && ((retry += TFTP_REXMT) < TFTP_TIMEOUT))
 
346
            {
 
347
              /* We resend our last ack.  */
 
348
#ifdef MDEBUG
 
349
              grub_printf ("<REXMT>\n");
 
350
#endif
 
351
              udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
 
352
                            iport, oport,
 
353
                            TFTP_MIN_PACKET, &tp);
 
354
              continue;
 
355
            }
 
356
#endif
 
357
          /* Timeout.  */
 
358
          break;
 
359
        }
 
360
      
 
361
      tr = (struct tftp_t *) &nic.packet[ETH_HLEN];
 
362
      if (tr->opcode == ntohs (TFTP_ERROR))
 
363
        {
 
364
          grub_printf ("TFTP error %d (%s)\n",
 
365
                       ntohs (tr->u.err.errcode),
 
366
                       tr->u.err.errmsg);
 
367
          break;
 
368
        }
 
369
      
 
370
      if (tr->opcode == ntohs (TFTP_OACK))
 
371
        {
 
372
          char *p = tr->u.oack.data, *e;
 
373
          
 
374
          /* Shouldn't happen.  */
 
375
          if (prevblock)
 
376
            /* Ignore it.  */
 
377
            continue;
 
378
          
 
379
          len = ntohs (tr->udp.len) - sizeof (struct udphdr) - 2;
 
380
          if (len > TFTP_MAX_PACKET)
 
381
            goto noak;
 
382
          
 
383
          e = p + len;
 
384
          while (*p != '\000' && p < e)
 
385
            {
 
386
              if (! grub_strcmp ("blksize", p))
 
387
                {
 
388
                  p += 8;
 
389
                  if ((packetsize = getdec (&p)) < TFTP_DEFAULTSIZE_PACKET)
 
390
                    goto noak;
 
391
                  
 
392
                  while (p < e && *p)
 
393
                    p++;
 
394
                  
 
395
                  if (p < e)
 
396
                    p++;
 
397
                }
 
398
              else
 
399
                {
 
400
                noak:
 
401
                  tp.opcode = htons (TFTP_ERROR);
 
402
                  tp.u.err.errcode = 8;
 
403
                  len = (grub_sprintf ((char *) tp.u.err.errmsg,
 
404
                                       "RFC1782 error")
 
405
                         + sizeof (tp.ip) + sizeof (tp.udp)
 
406
                         + sizeof (tp.opcode) + sizeof (tp.u.err.errcode)
 
407
                         + 1);
 
408
                  udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
 
409
                                iport, ntohs (tr->udp.src),
 
410
                                len, &tp);
 
411
                  return 0;
 
412
                }
 
413
            }
 
414
          
 
415
          if (p > e)
 
416
            goto noak;
 
417
          
 
418
          /* This ensures that the packet does not get processed as data!  */
 
419
          block = tp.u.ack.block = 0; 
 
420
        }
 
421
      else if (tr->opcode == ntohs (TFTP_DATA))
 
422
        {
 
423
          len = ntohs (tr->udp.len) - sizeof (struct udphdr) - 4;
 
424
          /* Shouldn't happen.  */
 
425
          if (len > packetsize)
 
426
            /* Ignore it.  */
 
427
            continue;
 
428
          
 
429
          block = ntohs (tp.u.ack.block = tr->u.data.block);
 
430
        }
 
431
      else
 
432
        /* Neither TFTP_OACK nor TFTP_DATA.  */
 
433
        break;
 
434
      
 
435
      if ((block || bcounter) && (block != prevblock + 1))
 
436
        /* Block order should be continuous */
 
437
        tp.u.ack.block = htons (block = prevblock);
 
438
      
 
439
      /* Should be continuous.  */
 
440
      tp.opcode = htons (TFTP_ACK);
 
441
      oport = ntohs (tr->udp.src);
 
442
      /* Ack.  */
 
443
      udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, iport,
 
444
                    oport, TFTP_MIN_PACKET, &tp);
 
445
      
 
446
      if ((unsigned short) (block - prevblock) != 1)
 
447
        /* Retransmission or OACK, don't process via callback
 
448
         * and don't change the value of prevblock.  */
 
449
        continue;
 
450
      
 
451
      prevblock = block;
 
452
      /* Is it the right place to zero the timer?  */
 
453
      retry = 0;
 
454
      
 
455
      if ((rc = fnc (tr->u.data.download,
 
456
                     ++bcounter, len, len < packetsize)) >= 0)
 
457
        return rc;
 
458
 
 
459
      /* End of data.  */
 
460
      if (len < packetsize)           
 
461
        return 1;
 
462
    }
 
463
  
 
464
  return 0;
 
465
}
 
466
 
 
467
/**************************************************************************
 
468
RARP - Get my IP address and load information
 
469
**************************************************************************/
 
470
int 
 
471
rarp (void)
 
472
{
 
473
  int retry;
 
474
 
 
475
  /* arp and rarp requests share the same packet structure.  */
 
476
  struct arprequest rarpreq;
 
477
 
 
478
  /* Make sure that an ethernet is probed.  */
 
479
  if (! eth_probe ())
 
480
    return 0;
 
481
 
 
482
  /* Clear the ready flag.  */
 
483
  network_ready = 0;
 
484
  
 
485
  grub_memset (&rarpreq, 0, sizeof (rarpreq));
 
486
 
 
487
  rarpreq.hwtype = htons (1);
 
488
  rarpreq.protocol = htons (IP);
 
489
  rarpreq.hwlen = ETH_ALEN;
 
490
  rarpreq.protolen = 4;
 
491
  rarpreq.opcode = htons (RARP_REQUEST);
 
492
  grub_memmove ((char *) &rarpreq.shwaddr, arptable[ARP_CLIENT].node,
 
493
                ETH_ALEN);
 
494
  /* sipaddr is already zeroed out */
 
495
  grub_memmove ((char *) &rarpreq.thwaddr, arptable[ARP_CLIENT].node,
 
496
                ETH_ALEN);
 
497
  /* tipaddr is already zeroed out */
 
498
 
 
499
  for (retry = 0; retry < MAX_ARP_RETRIES; ++retry)
 
500
    {
 
501
      long timeout;
 
502
      
 
503
      eth_transmit (broadcast, RARP, sizeof (rarpreq), &rarpreq);
 
504
 
 
505
      timeout = rfc2131_sleep_interval (TIMEOUT, retry);
 
506
      if (await_reply (AWAIT_RARP, 0, rarpreq.shwaddr, timeout))
 
507
        break;
 
508
 
 
509
      if (ip_abort)
 
510
        return 0;
 
511
    }
 
512
 
 
513
  if (retry < MAX_ARP_RETRIES)
 
514
    {
 
515
      network_ready = 1;
 
516
      return 1;
 
517
    }
 
518
 
 
519
  return 0;
 
520
}
 
521
 
 
522
/**************************************************************************
 
523
BOOTP - Get my IP address and load information
 
524
**************************************************************************/
 
525
int 
 
526
bootp (void)
 
527
{
 
528
  int retry;
 
529
#ifndef NO_DHCP_SUPPORT
 
530
  int reqretry;
 
531
#endif /* ! NO_DHCP_SUPPORT */
 
532
  struct bootpip_t ip;
 
533
  unsigned long starttime;
 
534
 
 
535
  /* Make sure that an ethernet is probed.  */
 
536
  if (! eth_probe ())
 
537
    return 0;
 
538
 
 
539
  /* Clear the ready flag.  */
 
540
  network_ready = 0;
 
541
 
 
542
#ifdef DEBUG
 
543
  grub_printf ("network is ready.\n");
 
544
#endif
 
545
  
 
546
  grub_memset (&ip, 0, sizeof (struct bootpip_t));
 
547
  ip.bp.bp_op = BOOTP_REQUEST;
 
548
  ip.bp.bp_htype = 1;
 
549
  ip.bp.bp_hlen = ETH_ALEN;
 
550
  starttime = currticks ();
 
551
  /* Use lower 32 bits of node address, more likely to be
 
552
     distinct than the time since booting */
 
553
  grub_memmove (&xid, &arptable[ARP_CLIENT].node[2], sizeof(xid));
 
554
  ip.bp.bp_xid = xid += htonl (starttime);
 
555
  grub_memmove (ip.bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETH_ALEN);
 
556
#ifdef DEBUG
 
557
  etherboot_printf ("bp_op = %d\n", ip.bp.bp_op);
 
558
  etherboot_printf ("bp_htype = %d\n", ip.bp.bp_htype);
 
559
  etherboot_printf ("bp_hlen = %d\n", ip.bp.bp_hlen);
 
560
  etherboot_printf ("bp_xid = %d\n", ip.bp.bp_xid);
 
561
  etherboot_printf ("bp_hwaddr = %!\n", ip.bp.bp_hwaddr);
 
562
  etherboot_printf ("bp_hops = %d\n", (int) ip.bp.bp_hops);
 
563
  etherboot_printf ("bp_secs = %d\n", (int) ip.bp.bp_hwaddr);
 
564
#endif
 
565
  
 
566
#ifdef  NO_DHCP_SUPPORT
 
567
  /* Request RFC-style options.  */
 
568
  grub_memmove (ip.bp.bp_vend, rfc1533_cookie, 5);
 
569
#else
 
570
  /* Request RFC-style options.  */
 
571
  grub_memmove (ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
 
572
  grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie, dhcpdiscover,
 
573
                sizeof dhcpdiscover);
 
574
  grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie + sizeof dhcpdiscover,
 
575
                rfc1533_end, sizeof rfc1533_end);
 
576
#endif /* ! NO_DHCP_SUPPORT */
 
577
 
 
578
  for (retry = 0; retry < MAX_BOOTP_RETRIES;)
 
579
    {
 
580
      long timeout;
 
581
 
 
582
#ifdef DEBUG
 
583
      grub_printf ("retry = %d\n", retry);
 
584
#endif
 
585
      
 
586
      /* Clear out the Rx queue first.  It contains nothing of
 
587
       * interest, except possibly ARP requests from the DHCP/TFTP
 
588
       * server.  We use polling throughout Etherboot, so some time
 
589
       * may have passed since we last polled the receive queue,
 
590
       * which may now be filled with broadcast packets.  This will
 
591
       * cause the reply to the packets we are about to send to be
 
592
       * lost immediately.  Not very clever.  */
 
593
      await_reply (AWAIT_QDRAIN, 0, NULL, 0);
 
594
 
 
595
      udp_transmit (IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
 
596
                    sizeof (struct bootpip_t), &ip);
 
597
      timeout = rfc2131_sleep_interval (TIMEOUT, retry++);
 
598
#ifdef NO_DHCP_SUPPORT
 
599
      if (await_reply (AWAIT_BOOTP, 0, NULL, timeout))
 
600
        {
 
601
          network_ready = 1;
 
602
          return 1;
 
603
        }
 
604
#else /* ! NO_DHCP_SUPPORT */
 
605
      if (await_reply (AWAIT_BOOTP, 0, NULL, timeout))
 
606
        {
 
607
          if (dhcp_reply != DHCPOFFER)
 
608
            {
 
609
              network_ready = 1;
 
610
              return 1;
 
611
            }
 
612
 
 
613
          dhcp_reply = 0;
 
614
#ifdef DEBUG
 
615
  etherboot_printf ("bp_op = %d\n", (int) ip.bp.bp_op);
 
616
  etherboot_printf ("bp_htype = %d\n", (int) ip.bp.bp_htype);
 
617
  etherboot_printf ("bp_hlen = %d\n", (int) ip.bp.bp_hlen);
 
618
  etherboot_printf ("bp_xid = %d\n", (int) ip.bp.bp_xid);
 
619
  etherboot_printf ("bp_hwaddr = %!\n", ip.bp.bp_hwaddr);
 
620
  etherboot_printf ("bp_hops = %d\n", (int) ip.bp.bp_hops);
 
621
  etherboot_printf ("bp_secs = %d\n", (int) ip.bp.bp_hwaddr);
 
622
#endif
 
623
          grub_memmove (ip.bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
 
624
          grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie,
 
625
                        dhcprequest, sizeof dhcprequest);
 
626
          grub_memmove (ip.bp.bp_vend + sizeof rfc1533_cookie
 
627
                        + sizeof dhcprequest,
 
628
                        rfc1533_end, sizeof rfc1533_end);
 
629
          grub_memmove (ip.bp.bp_vend + 9, (char *) &dhcp_server,
 
630
                        sizeof (in_addr));
 
631
          grub_memmove (ip.bp.bp_vend + 15, (char *) &dhcp_addr,
 
632
                        sizeof (in_addr));
 
633
#ifdef DEBUG
 
634
          grub_printf ("errnum = %d\n", errnum);
 
635
#endif
 
636
          for (reqretry = 0; reqretry < MAX_BOOTP_RETRIES;)
 
637
            {
 
638
              int ret;
 
639
#ifdef DEBUG
 
640
              grub_printf ("reqretry = %d\n", reqretry);
 
641
#endif
 
642
              
 
643
              ret = udp_transmit (IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
 
644
                                  sizeof (struct bootpip_t), &ip);
 
645
              if (! ret)
 
646
                grub_printf ("udp_transmit failed.\n");
 
647
              
 
648
              dhcp_reply = 0;
 
649
              timeout = rfc2131_sleep_interval (TIMEOUT, reqretry++);
 
650
              if (await_reply (AWAIT_BOOTP, 0, NULL, timeout))
 
651
                if (dhcp_reply == DHCPACK)
 
652
                  {
 
653
                    network_ready = 1;
 
654
                    return 1;
 
655
                  }
 
656
 
 
657
#ifdef DEBUG
 
658
              grub_printf ("dhcp_reply = %d\n", dhcp_reply);
 
659
#endif
 
660
              
 
661
              if (ip_abort)
 
662
                return 0;
 
663
            }
 
664
        }
 
665
#endif /* ! NO_DHCP_SUPPORT */
 
666
      
 
667
      if (ip_abort)
 
668
        return 0;
 
669
      
 
670
      ip.bp.bp_secs = htons ((currticks () - starttime) / TICKS_PER_SEC);
 
671
    }
 
672
 
 
673
  /* Timeout.  */
 
674
  return 0;
 
675
}
 
676
 
 
677
/**************************************************************************
 
678
UDPCHKSUM - Checksum UDP Packet (one of the rare cases when assembly is
 
679
            actually simpler...)
 
680
 RETURNS: checksum, 0 on checksum error. This
 
681
          allows for using the same routine for RX and TX summing:
 
682
          RX  if (packet->udp.chksum && udpchksum(packet))
 
683
                  error("checksum error");
 
684
          TX  packet->udp.chksum=0;
 
685
              if (0==(packet->udp.chksum=udpchksum(packet)))
 
686
                  packet->upd.chksum=0xffff;
 
687
**************************************************************************/
 
688
static inline void
 
689
dosum (unsigned short *start, unsigned int len, unsigned short *sum)
 
690
{
 
691
  __asm__ __volatile__
 
692
    ("clc\n"
 
693
     "1:\tlodsw\n\t"
 
694
     "xchg %%al,%%ah\n\t"       /* convert to host byte order */
 
695
     "adcw %%ax,%0\n\t"         /* add carry of previous iteration */
 
696
     "loop 1b\n\t"
 
697
     "adcw $0,%0"               /* add carry of last iteration */
 
698
     : "=b" (*sum), "=S"(start), "=c"(len)
 
699
     : "0"(*sum), "1"(start), "2"(len)
 
700
     : "ax", "cc"
 
701
     );
 
702
}
 
703
 
 
704
/* UDP sum:
 
705
 * proto, src_ip, dst_ip, udp_dport, udp_sport, 2*udp_len, payload
 
706
 */
 
707
static unsigned short
 
708
udpchksum (struct iphdr *packet)
 
709
{
 
710
  int len = ntohs (packet->len);
 
711
  unsigned short rval;
 
712
  
 
713
  /* add udplength + protocol number */
 
714
  rval = (len - sizeof (struct iphdr)) + IP_UDP;
 
715
  
 
716
  /* pad to an even number of bytes */
 
717
  if (len % 2) {
 
718
    ((char *) packet)[len++] = 0;
 
719
  }
 
720
  
 
721
  /* sum over src/dst ipaddr + udp packet */
 
722
  len -= (char *) &packet->src - (char *) packet;
 
723
  dosum ((unsigned short *) &packet->src, len >> 1, &rval);
 
724
  
 
725
  /* take one's complement */
 
726
  return ~rval;
 
727
}
 
728
 
 
729
/**************************************************************************
 
730
AWAIT_REPLY - Wait until we get a response for our request
 
731
**************************************************************************/
 
732
int 
 
733
await_reply (int type, int ival, void *ptr, int timeout)
 
734
{
 
735
  unsigned long time;
 
736
  struct iphdr *ip;
 
737
  struct udphdr *udp;
 
738
  struct arprequest *arpreply;
 
739
  struct bootp_t *bootpreply;
 
740
  unsigned short ptype;
 
741
  unsigned int protohdrlen = (ETH_HLEN + sizeof (struct iphdr)
 
742
                              + sizeof (struct udphdr));
 
743
 
 
744
  /* Clear the abort flag.  */
 
745
  ip_abort = 0;
 
746
  
 
747
  time = timeout + currticks ();
 
748
  /* The timeout check is done below.  The timeout is only checked if
 
749
   * there is no packet in the Rx queue.  This assumes that eth_poll()
 
750
   * needs a negligible amount of time.  */
 
751
  for (;;)
 
752
    {
 
753
      if (eth_poll ())
 
754
        {
 
755
          /* We have something!  */
 
756
          
 
757
          /* Check for ARP - No IP hdr.  */
 
758
          if (nic.packetlen >= ETH_HLEN)
 
759
            {
 
760
              ptype = (((unsigned short) nic.packet[12]) << 8
 
761
                       | ((unsigned short) nic.packet[13]));
 
762
            }
 
763
          else
 
764
            /* What else could we do with it?  */
 
765
            continue;
 
766
          
 
767
          if (nic.packetlen >= ETH_HLEN + sizeof (struct arprequest)
 
768
              && ptype == ARP)
 
769
            {
 
770
              unsigned long tmp;
 
771
 
 
772
              arpreply = (struct arprequest *) &nic.packet[ETH_HLEN];
 
773
              
 
774
              if (arpreply->opcode == htons (ARP_REPLY)
 
775
                  && ! grub_memcmp (arpreply->sipaddr, ptr, sizeof (in_addr))
 
776
                  && type == AWAIT_ARP)
 
777
                {
 
778
                  grub_memmove ((char *) arptable[ival].node,
 
779
                                arpreply->shwaddr,
 
780
                                ETH_ALEN);
 
781
                  return 1;
 
782
                }
 
783
              
 
784
              grub_memmove ((char *) &tmp, arpreply->tipaddr,
 
785
                            sizeof (in_addr));
 
786
              
 
787
              if (arpreply->opcode == htons (ARP_REQUEST)
 
788
                  && tmp == arptable[ARP_CLIENT].ipaddr.s_addr)
 
789
                {
 
790
                  arpreply->opcode = htons (ARP_REPLY);
 
791
                  grub_memmove (arpreply->tipaddr, arpreply->sipaddr,
 
792
                                sizeof (in_addr));
 
793
                  grub_memmove (arpreply->thwaddr, (char *) arpreply->shwaddr,
 
794
                                ETH_ALEN);
 
795
                  grub_memmove (arpreply->sipaddr,
 
796
                                (char *) &arptable[ARP_CLIENT].ipaddr,
 
797
                                sizeof (in_addr));
 
798
                  grub_memmove (arpreply->shwaddr,
 
799
                                arptable[ARP_CLIENT].node,
 
800
                                ETH_ALEN);
 
801
                  eth_transmit (arpreply->thwaddr, ARP,
 
802
                                sizeof (struct arprequest),
 
803
                                arpreply);
 
804
#ifdef MDEBUG
 
805
                  grub_memmove (&tmp, arpreply->tipaddr, sizeof (in_addr));
 
806
                  etherboot_printf ("Sent ARP reply to: %@\n", tmp);
 
807
#endif  /* MDEBUG */
 
808
                }
 
809
              
 
810
              continue;
 
811
            }
 
812
 
 
813
          if (type == AWAIT_QDRAIN)
 
814
            continue;
 
815
          
 
816
          /* Check for RARP - No IP hdr.  */
 
817
          if (type == AWAIT_RARP
 
818
              && nic.packetlen >= ETH_HLEN + sizeof (struct arprequest)
 
819
              && ptype == RARP)
 
820
            {
 
821
              arpreply = (struct arprequest *) &nic.packet[ETH_HLEN];
 
822
              
 
823
              if (arpreply->opcode == htons (RARP_REPLY)
 
824
                  && ! grub_memcmp (arpreply->thwaddr, ptr, ETH_ALEN))
 
825
                {
 
826
                  grub_memmove ((char *) arptable[ARP_SERVER].node,
 
827
                                arpreply->shwaddr, ETH_ALEN);
 
828
                  grub_memmove ((char *) &arptable[ARP_SERVER].ipaddr,
 
829
                                arpreply->sipaddr, sizeof (in_addr));
 
830
                  grub_memmove ((char *) &arptable[ARP_CLIENT].ipaddr,
 
831
                                arpreply->tipaddr, sizeof (in_addr));
 
832
                  return 1;
 
833
                }
 
834
              
 
835
              continue;
 
836
            }
 
837
 
 
838
          /* Anything else has IP header.  */
 
839
          if (nic.packetlen < protohdrlen || ptype != IP)
 
840
            continue;
 
841
          
 
842
          ip = (struct iphdr *) &nic.packet[ETH_HLEN];
 
843
          if (ip->verhdrlen != 0x45
 
844
              || ipchksum ((unsigned short *) ip, sizeof (struct iphdr))
 
845
              || ip->protocol != IP_UDP)
 
846
            continue;
 
847
          
 
848
          /*
 
849
            - Till Straumann <Till.Straumann@TU-Berlin.de>
 
850
            added udp checksum (safer on a wireless link)
 
851
            added fragmentation check: I had a corrupted image
 
852
            in memory due to fragmented TFTP packets - took me
 
853
            3 days to find the cause for this :-(
 
854
          */
 
855
          
 
856
          /* If More Fragments bit and Fragment Offset field
 
857
             are non-zero then packet is fragmented */
 
858
          if (ip->frags & htons(0x3FFF))
 
859
            {
 
860
              grub_printf ("ALERT: got a fragmented packet - reconfigure your server\n");
 
861
              continue;
 
862
            }
 
863
          
 
864
          udp = (struct udphdr *) &nic.packet[(ETH_HLEN
 
865
                                               + sizeof (struct iphdr))];
 
866
          if (udp->chksum && udpchksum (ip))
 
867
            {
 
868
              grub_printf ("UDP checksum error\n");
 
869
              continue;
 
870
            }
 
871
          
 
872
          /* BOOTP ?  */
 
873
          bootpreply = (struct bootp_t *)
 
874
            &nic.packet[(ETH_HLEN + sizeof (struct iphdr)
 
875
                         + sizeof (struct udphdr))];
 
876
          if (type == AWAIT_BOOTP
 
877
#ifdef NO_DHCP_SUPPORT
 
878
              && (nic.packetlen >= (ETH_HLEN + sizeof (struct bootp_t)))
 
879
#else
 
880
              && (nic.packetlen
 
881
                  >= (ETH_HLEN + sizeof (struct bootp_t) - DHCP_OPT_LEN))
 
882
#endif /* ! NO_DHCP_SUPPORT */
 
883
              && udp->dest == htons (BOOTP_CLIENT)
 
884
              && bootpreply->bp_op == BOOTP_REPLY
 
885
              && bootpreply->bp_xid == xid
 
886
              && (! grub_memcmp (broadcast, bootpreply->bp_hwaddr, ETH_ALEN)
 
887
                  || ! grub_memcmp (arptable[ARP_CLIENT].node,
 
888
                                    bootpreply->bp_hwaddr, ETH_ALEN)))
 
889
            {
 
890
#ifdef DEBUG
 
891
              grub_printf ("BOOTP packet was received.\n");
 
892
#endif
 
893
              arptable[ARP_CLIENT].ipaddr.s_addr
 
894
                = bootpreply->bp_yiaddr.s_addr;
 
895
#ifndef NO_DHCP_SUPPORT
 
896
              dhcp_addr.s_addr = bootpreply->bp_yiaddr.s_addr;
 
897
#ifdef DEBUG
 
898
              etherboot_printf ("dhcp_addr = %@\n", dhcp_addr.s_addr);
 
899
#endif
 
900
#endif /* ! NO_DHCP_SUPPORT */
 
901
              netmask = default_netmask ();
 
902
              arptable[ARP_SERVER].ipaddr.s_addr
 
903
                = bootpreply->bp_siaddr.s_addr;
 
904
              /* Kill arp.  */
 
905
              grub_memset (arptable[ARP_SERVER].node, 0, ETH_ALEN);
 
906
              arptable[ARP_GATEWAY].ipaddr.s_addr
 
907
                = bootpreply->bp_giaddr.s_addr;
 
908
              /* Kill arp.  */
 
909
              grub_memset (arptable[ARP_GATEWAY].node, 0, ETH_ALEN);
 
910
 
 
911
              grub_memmove ((char *) BOOTP_DATA_ADDR, (char *) bootpreply,
 
912
                            sizeof (struct bootpd_t));
 
913
#ifdef NO_DHCP_SUPPORT
 
914
              decode_rfc1533 (BOOTP_DATA_ADDR->bootp_reply.bp_vend,
 
915
                              0, BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN, 1);
 
916
#else
 
917
              decode_rfc1533 (BOOTP_DATA_ADDR->bootp_reply.bp_vend,
 
918
                              0, DHCP_OPT_LEN + MAX_BOOTP_EXTLEN, 1);
 
919
#endif /* ! NO_DHCP_SUPPORT */
 
920
              
 
921
              return 1;
 
922
            }
 
923
          
 
924
          /* TFTP ? */
 
925
          if (type == AWAIT_TFTP && ntohs (udp->dest) == ival)
 
926
            return 1;
 
927
        }
 
928
      else
 
929
        {
 
930
          /* Check for abort key only if the Rx queue is empty -
 
931
           * as long as we have something to process, don't
 
932
           * assume that something failed.  It is unlikely that
 
933
           * we have no processing time left between packets.  */
 
934
          if (checkkey () != -1 && ASCII_CHAR (getkey ()) == CTRL_C)
 
935
            {
 
936
              ip_abort = 1;
 
937
              return 0;
 
938
            }
 
939
          
 
940
          /* Do the timeout after at least a full queue walk.  */
 
941
          if ((timeout == 0) || (currticks() > time))
 
942
            {
 
943
              break;
 
944
            }
 
945
        }
 
946
    }
 
947
  
 
948
  return 0;
 
949
}
 
950
 
 
951
/**************************************************************************
 
952
DECODE_RFC1533 - Decodes RFC1533 header
 
953
**************************************************************************/
 
954
int
 
955
decode_rfc1533 (unsigned char *p, int block, int len, int eof)
 
956
{
 
957
  static unsigned char *extdata = NULL, *extend = NULL;
 
958
  unsigned char *extpath = NULL;
 
959
  unsigned char *endp;
 
960
  
 
961
  if (block == 0)
 
962
    {
 
963
      end_of_rfc1533 = NULL;
 
964
      vendorext_isvalid = 0;
 
965
      
 
966
      if (grub_memcmp (p, rfc1533_cookie, 4))
 
967
        /* no RFC 1533 header found */
 
968
        return 0;
 
969
      
 
970
      p += 4;
 
971
      endp = p + len;
 
972
    }
 
973
  else
 
974
    {
 
975
      if (block == 1)
 
976
        {
 
977
          if (grub_memcmp (p, rfc1533_cookie, 4))
 
978
            /* no RFC 1533 header found */
 
979
            return 0;
 
980
          
 
981
          p += 4;
 
982
          len -= 4;
 
983
        }
 
984
      
 
985
      if (extend + len
 
986
          <= ((unsigned char *)
 
987
              &(BOOTP_DATA_ADDR->bootp_extension[MAX_BOOTP_EXTLEN])))
 
988
        {
 
989
          grub_memmove (extend, p, len);
 
990
          extend += len;
 
991
        }
 
992
      else
 
993
        {
 
994
          grub_printf ("Overflow in vendor data buffer! Aborting...\n");
 
995
          *extdata = RFC1533_END;
 
996
          return 0;
 
997
        }
 
998
      
 
999
      p = extdata;
 
1000
      endp = extend;
 
1001
    }
 
1002
 
 
1003
  if (! eof)
 
1004
    return -1;
 
1005
  
 
1006
  while (p < endp)
 
1007
    {
 
1008
      unsigned char c = *p;
 
1009
      
 
1010
      if (c == RFC1533_PAD)
 
1011
        {
 
1012
          p++;
 
1013
          continue;
 
1014
        }
 
1015
      else if (c == RFC1533_END)
 
1016
        {
 
1017
          end_of_rfc1533 = endp = p;
 
1018
          continue;
 
1019
        }
 
1020
      else if (c == RFC1533_NETMASK)
 
1021
        {
 
1022
          grub_memmove ((char *) &netmask, p + 2, sizeof (in_addr));
 
1023
        }
 
1024
      else if (c == RFC1533_GATEWAY)
 
1025
        {
 
1026
          /* This is a little simplistic, but it will
 
1027
             usually be sufficient.
 
1028
             Take only the first entry.  */
 
1029
          if (TAG_LEN (p) >= sizeof (in_addr))
 
1030
            grub_memmove ((char *) &arptable[ARP_GATEWAY].ipaddr, p + 2,
 
1031
                          sizeof (in_addr));
 
1032
        }
 
1033
      else if (c == RFC1533_EXTENSIONPATH)
 
1034
        extpath = p;
 
1035
#ifndef NO_DHCP_SUPPORT
 
1036
      else if (c == RFC2132_MSG_TYPE)
 
1037
        {
 
1038
          dhcp_reply = *(p + 2);
 
1039
        }
 
1040
      else if (c == RFC2132_SRV_ID)
 
1041
        {
 
1042
          grub_memmove ((char *) &dhcp_server, p + 2, sizeof (in_addr));
 
1043
#ifdef DEBUG
 
1044
          etherboot_printf ("dhcp_server = %@\n", dhcp_server.s_addr);
 
1045
#endif
 
1046
        }
 
1047
#endif /* ! NO_DHCP_SUPPORT */
 
1048
      else if (c == RFC1533_VENDOR_MAGIC
 
1049
               && TAG_LEN(p) >= 6
 
1050
               && ! grub_memcmp (p + 2, vendorext_magic, 4)
 
1051
               && p[6] == RFC1533_VENDOR_MAJOR)
 
1052
        vendorext_isvalid++;
 
1053
      /* GRUB now handles its own tag. Get the name of a configuration
 
1054
         file from the network. Cool...  */
 
1055
      else if (c == RFC1533_VENDOR_CONFIGFILE)
 
1056
        {
 
1057
          int l = TAG_LEN (p);
 
1058
          
 
1059
          /* Eliminate the trailing NULs according to RFC 2132.  */
 
1060
          while (*(p + 2 + l - 1) == '\000' && l > 0)
 
1061
            l--;
 
1062
          
 
1063
          /* XXX: Should check if LEN is less than the maximum length
 
1064
             of CONFIG_FILE. This kind of robustness will be a goal
 
1065
             in GRUB 1.0.  */
 
1066
          grub_memmove (config_file, p + 2, l);
 
1067
          config_file[l] = 0;
 
1068
        }
 
1069
      
 
1070
      p += TAG_LEN (p) + 2;
 
1071
    }
 
1072
  
 
1073
  extdata = extend = endp;
 
1074
  
 
1075
  /* Perhaps we can eliminate this because we doesn't require so
 
1076
     much information, but I leave this alone.  */
 
1077
  if (block == 0 && extpath != NULL)
 
1078
    {
 
1079
      char fname[64];
 
1080
      int fnamelen = TAG_LEN (extpath);
 
1081
      
 
1082
      while (*(extpath + 2 + fnamelen - 1) == '\000' && fnamelen > 0)
 
1083
        fnamelen--;
 
1084
      
 
1085
      if (fnamelen + 1 > sizeof (fname))
 
1086
        {
 
1087
          grub_printf ("Too long file name for Extensions Path\n");
 
1088
          return 0;
 
1089
        }
 
1090
      else if (! fnamelen)
 
1091
        {
 
1092
          grub_printf ("Empty file name for Extensions Path\n");
 
1093
          return 0;
 
1094
        }
 
1095
      
 
1096
      grub_memmove (fname, extpath + 2, fnamelen);
 
1097
      fname[fnamelen] = '\000';
 
1098
      grub_printf ("Loading BOOTP-extension file: %s\n", fname);
 
1099
      tftp (fname, decode_rfc1533);
 
1100
    }
 
1101
  
 
1102
  /* Proceed with next block.  */
 
1103
  return -1;
 
1104
}
 
1105
 
 
1106
/**************************************************************************
 
1107
IPCHKSUM - Checksum IP Header
 
1108
**************************************************************************/
 
1109
static unsigned short 
 
1110
ipchksum (unsigned short *ip, int len)
 
1111
{
 
1112
  unsigned long sum = 0;
 
1113
  len >>= 1;
 
1114
  while (len--)
 
1115
    {
 
1116
      sum += *(ip++);
 
1117
      if (sum > 0xFFFF)
 
1118
        sum -= 0xFFFF;
 
1119
    }
 
1120
  return (~sum) & 0x0000FFFF;
 
1121
}
 
1122
 
 
1123
#define TWO_SECOND_DIVISOR (2147483647l/TICKS_PER_SEC)
 
1124
 
 
1125
/**************************************************************************
 
1126
RFC2131_SLEEP_INTERVAL - sleep for expotentially longer times
 
1127
**************************************************************************/
 
1128
long
 
1129
rfc2131_sleep_interval (int base, int exp)
 
1130
{
 
1131
  static long seed = 0;
 
1132
  long q;
 
1133
  unsigned long tmo;
 
1134
  
 
1135
#ifdef BACKOFF_LIMIT
 
1136
  if (exp > BACKOFF_LIMIT)
 
1137
    exp = BACKOFF_LIMIT;
 
1138
#endif
 
1139
  if (!seed)
 
1140
    /* Initialize linear congruential generator */
 
1141
    seed = (currticks () + *((long *) &arptable[ARP_CLIENT].node)
 
1142
            + ((short *) arptable[ARP_CLIENT].node)[2]);
 
1143
  /* simplified version of the LCG given in Bruce Schneier's
 
1144
     "Applied Cryptography" */
 
1145
  q = seed / 53668;
 
1146
  if ((seed = 40014 * (seed - 53668 * q) - 12211 *q ) < 0)
 
1147
    seed += 2147483563L;
 
1148
  tmo = (base << exp) + (TICKS_PER_SEC - (seed / TWO_SECOND_DIVISOR));
 
1149
  return tmo;
 
1150
}
 
1151
 
 
1152
/**************************************************************************
 
1153
CLEANUP - shut down networking
 
1154
**************************************************************************/
 
1155
void
 
1156
cleanup_net (void)
 
1157
{
 
1158
  if (network_ready)
 
1159
    {
 
1160
      /* Stop receiving packets.  */
 
1161
      eth_disable ();
 
1162
      network_ready = 0;
 
1163
    }
 
1164
}