home *** CD-ROM | disk | FTP | other *** search
- #include "protocol.h"
- #include "bootinc.h"
-
-
- /* Originally some of this was part of NCSA Telnet.
- Modifications Apr/May 1993 Jamie Honan
- */
-
- unsigned char bseed[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
- ltseed[] = {0x00, 0x00, 0xff, 0x48, 0x00, 0x00};
-
- unsigned char raw[RAW_LENGTH];
-
- unsigned char
- nnmyaddr[DADDLEN], /* my ethernet hardware
- * address */
- broadaddr[DADDLEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, /* the broadcast address */
-
- nnipnum[4], /* my ip number */
- #ifdef BROADCAST0
- broadip[4] = {0, 0, 0, 0},
- #else
- broadip[4] = {0xff, 0xff, 0xff, 0xff},
- #endif
- nnserveraddr[DADDLEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, /* server's ethernet
-
- * hardware address */
- nnipserver[4] = {0xff, 0xff, 0xff, 0xff}; /* server's ip number */
-
- int
- nnipident = 1; /* ident field of outgoing ip
- * packets */
-
- int debug = 0;
-
- struct pseudotcp tcps; /* for checksums */
- struct pseudotcp utcps; /* for checksums */
-
- DLAYER blankd;
- IPKT blankip;
-
- UDPKT udpout;
- UDPKT udp_rxdata;
-
- /************************************************************************/
- /* neterrstring
- * returns the string associated with a particular error number
- */
- typedef struct
- {
- int errno;
- char *errstring;
- } ERRS;
-
- static ERRS errs[] = {
- { 0 , "Error unknown"},
- { 100, "Network jammed, probable break in wire"},
- { 101, "Could not initialize hardware level network driver"},
- { 102, "ERROR: The conflicting machine is using the same IP number"},
- { 103, "RARP request failed, an IP number is required"},
- { 300, "Bad IP checksum"},
- { 301, "IP packet not for me"},
- { 302, "IP packet with options received"},
- { 303, "IP: unknown higher layer protocol"},
- { 304, "IP: fragmented packet received, frags not supported"},
- { 400, "TCP: bad checksum"},
- { 401, "ACK invalid for TCP syn sent"},
- { 403, "TCP in unknown state"},
- { 404, "Invalid port for TCPsend"},
- { 405, "TCP connection reset by other host"},
- { 406, "Null port specified for ackandtrans"},
- { 407, "Packet received for invalid port -- reset sent"},
- { 500, "No internal TCP ports available"},
- { 501, "Warning: Event queue filled, probably non-fatal"},
- { 504, "Local host or gateway not responding"},
- { 505, "Memory allocation error, cannot open port"},
- { 506, "Not allowed to connect to broadcast address"},
- { 507, "Reset received: syn sent, host is refusing connection"},
- { 600, "ICMP: Echo reply"},
- { 603, "ICMP: Destination unreachable"},
- { 604, "ICMP: Source Quench"},
- { 605, "ICMP: Redirect, another gateway is more efficient"},
- { 608, "ICMP: Echo requested (ping requested)"},
- { 611, "ICMP: Time Exceeded on Packet"},
- { 612, "ICMP: Parameter problem in IP"},
- { 613, "ICMP: Timestamp request"},
- { 614, "ICMP: Timestamp reply"},
- { 615, "ICMP: Information request"},
- { 616, "ICMP: Information reply"},
- { 630, "ICMP: Network Unreachable"},
- { 631, "ICMP: Host Unreachable"},
- { 632, "ICMP: Protocol Unreachable"},
- { 633, "ICMP: Port Unreachable"},
- { 634, "ICMP: Frgamentation needed and DF set"},
- { 635, "ICMP: Source route Failed"},
- { 636, "ICMP: Destination network unknown"},
- { 637, "ICMP: Destination host unknown"},
- { 638, "ICMP: Source host isolated"},
- { 639, "ICMP: Dest network administratively prohibited"},
- { 640, "ICMP: Dest host administratively prohibited"},
- { 641, "ICMP: Network unreachable for type of service"},
- { 642, "ICMP: Host unreachable for type of service"},
- { 699, "ICMP: Checksum error"},
- { 700, "Bad UDP checksum"},
- { 800, "Domain: Name request to server failed"},
- { 801, "Domain: Using default domain"},
- { 802, "Domain: name does not exist"},
- { 803, "Domain: UDP name server did not resolve the name"},
- { 804, "Domain: name server failed, unknown reason"},
- { 805, "Host machine not in configuration file"},
- { 806, "Missing IP number, requires domain lookup"},
- { 900, "Session: Cannot find or open configuration file"},
- { 901, "Session: Cannot allocate memory for processing"},
- { 902, "Session: Invalid keyword in configuration file"},
- { 903, "Session: Element too long (>200), maybe missing quote"},
- { 904, "Session: Probable missing quote marks, a field must be on one line"},
- { 905, "Session: 'name' field required before other machine entries"},
- { 906, "Session: Syntax error, invalid IP number"},
- { 907, "Session: Syntax error, Subnet mask invalid"},
- { 908, "Session: Syntax error, IP address for this PC is invalid"},
- { 1000, "Bootp: No Response from bootpd server"},
- { 1001, "Bootp: Invalid bootp packet response from server"},
- { 1020, "Tftp: No response"},
- { 1021, "Tftp: host refused"},
- { 1022, "Tftp: protocol error"},
- { 2000, "Terminated network boot process"},
- { 3000, "Image: Not executable"},
- { 3001, "Image: header length incorrect"},
- { 3002, "Image: attempt to place data incorrectly"},
- { 3003, "Image: image record length incorrect"},
- { 3004, "Image: too much data"},
- { 3005, "Image: address overflow"},
- { 3011, "Image: parity error during extended memory transfer"},
- { 3012, "Image: interrupt error during extended memory transfer"},
- { 3013, "Image: line 20 gating error during extended memory transfer"},
- { -1, "" }
- };
-
- static char errspace[80]; /* room for user-defined
- * errors */
-
- char *
- neterrstring(int errno)
- {
- int i;
- char s[10];
-
- if (errno < 0)
- return (errspace);
- for (i = 0; errs[i].errno >= 0; i++)
- {
- if (errs[i].errno == errno)
- return (errs[i].errstring); /* pointer to error message */
- }
- return (errs[0].errstring); /* error unknown */
- }
-
- void
- netposterr(num)
- int num;
- {
- n_printf("%d %s\n", num, neterrstring(num));
- }
-
- void
- n_puts(char *s)
- {
- while (*s)
- {
- if (*s == '\n')
- n_putchar('\r');
- n_putchar(*s++);
- }
- }
-
- void n_putscrlf(char *s)
- {
- n_puts(s);
- n_puts("\n");
- }
-
- void
- etherinit(void)
- {
- memcpy(broadaddr, bseed, DADDLEN);
- memcpy(blankd.dest, broadaddr, DADDLEN); /* some are broadcast */
- memcpy(blankd.me, nnmyaddr, DADDLEN); /* always from me */
- blankd.type = EIP; /* mostly IP packets */
- }
-
- /*************************************************************************/
- /*
- * ipinit ()
- *
- * initialize on packet to use for internet transmission -- most packets will
- * be tcp/udp, so they will be initialized at a different layer, but some
- * require a generic ip packet.
- *
- * Also takes a guess at setting a netmask if it hasn't happened by now.
- *
- */
- void
- ipinit(void)
- {
- memcpy(&blankip.d, &blankd, sizeof(DLAYER));
- blankip.i.versionandhdrlen = 0x45; /* smallest header, version 4 */
- blankip.i.service = 0; /* normal service */
- blankip.i.tlen = 576; /* no data yet, maximum size */
- blankip.i.ident = 0;
- blankip.i.frags = 0; /* not a fragment of a packet */
- blankip.i.ttl = 100; /* 100 seconds should be enough */
- blankip.i.protocol = PROTUDP; /* default to UDP */
- blankip.i.check = 0; /* disable checksums for now */
- memcpy(blankip.i.ipsource, nnipnum, 4); /* my return address */
- memcpy(blankip.i.ipdest, broadip, 4); /* to ? */
- }
-
- /**************************************************************************/
- /*
- * udpinit ()
- *
- * Setup ulist for receive of udp packets
- *
- */
- void
- udpinit(void)
- {
- memcpy(&udpout, &blankip, sizeof(DLAYER) + sizeof(IPLAYER));
- udpout.i.protocol = PROTUDP; /* UDP type */
- utcps.z = 0;
- utcps.proto = PROTUDP;
- memcpy(utcps.source, nnipnum, 4);
- }
-
- void
- udp_reinit(void)
- {
- /* The boot protocol has given us more specific information */
-
- memcpy(blankd.dest, nnserveraddr, DADDLEN);
- memcpy(udpout.d.dest, nnserveraddr, DADDLEN);
- memcpy(blankd.me, nnmyaddr, DADDLEN);
- memcpy(udpout.d.me, nnmyaddr, DADDLEN);
- memcpy(blankip.i.ipsource, nnipnum, 4);
- memcpy(udpout.i.ipsource, nnipnum, 4);
- memcpy(utcps.source, nnipnum, 4);
- }
-
- /**************************************************************************/
- /*
- * netinit ()
- *
- * Handles all the initialization to bring up the network connection.
- * Assumes that the configuration file has already been read up.
- * (called from Snetinit () )
- *
- * Returns 0 on successful initialization.
- *
- */
- int
- netinit(void)
- {
- int ret;
-
- /*
- * Initializes all buffers and hardware for data link layer.
- * Machine/board dependent.
- */
- ret = dlayerinit();
- if (ret)
- {
- switch (ret)
- {
- case -10:
- n_printf("Need a function for opening board!!\n");
- break;
-
- default:
- n_printf("Board initialization failed!. Error code=%d\n", ret);
- break;
- } /* end switch */
- netposterr(101);
- return (ret);
- }
- n_printf("Ethernet address %x:%x:%x:%x:%x:%x\n",
- nnmyaddr[0], nnmyaddr[1], nnmyaddr[2],
- nnmyaddr[3], nnmyaddr[4], nnmyaddr[5]);
- return (0);
- }
-
-
- int
- init(char *ifname)
- {
- n_printf("Network boot. Press x to terminate.\n");
- netconfig(ifname);
-
- if (netinit() != 0)
- { /* starts up hardware */
- return (0); /* netinit() failed */
- }
-
- etherinit(); /* dlayer packets */
- ipinit(); /* ip packets */
- udpinit(); /* udp packets */
- return 1;
- }
-
- /*
- char hexbar[] = "0123456789ABCDEF";
-
- void int2hex(char *p, int i)
- {
- *p++ = hexbar[(i>>4) & 0xf];
- *p = hexbar[i & 0xf];
- }
-
-
- void initbootname(char *name, unsigned char *inetad)
- {
- int2hex(&name[0], inetad[0]);
- int2hex(&name[2], inetad[1]);
- int2hex(&name[4], inetad[2]);
- int2hex(&name[6], inetad[3]);
- name[8] = '.';
- name[9] = 'i';
- name[10] = '8';
- name[11] = '6';
- name[12] = '\0';
- }
-
- */
- static long next = 1;
-
- void
- startrand(unsigned int seed)
- {
- next = seed;
- }
-
- int
- random(int mask) /* not really - I think %
- * limit stops it */
- {
- next = n_lmul(next, 1103515245) + 12345;
- return ((short) ((next >> 16) & mask));
- }
-
- long
- n_ticks(void)
- {
- static long lastticks = 0;
- static long baseticks = 0;
- long nowt;
-
- nowt = *(long far *) (MK_FP(0x40, 0x6c));
-
- if (nowt < lastticks)
- {
- /* timer wrap around */
- baseticks += ((182L * 24 * 36000) / 10);
- /* I think the bios actually uses 0x1800b0 */
- }
- lastticks = nowt;
- return (nowt + baseticks);
- }
-
- long
- n_secs(void)
- {
- /* expects (long divisor) (long dividend) returns dx:ax */
- return n_ldiv(n_lmul(n_ticks(), 10), 182L);
- }
-
- /* This n_printf only does %x %d %s %c and %lx %ld AND %ls - special for far string
- Also %p near pointer and %lp far pointer
- Does \r append on \n
- Only good for 8086 type machines in small model
- Has special allowance in case DS != SS
- */
-
- #define MAX_OUTLEN 15
-
- static
- pnum(long i, int base)
- {
- static char obuf[MAX_OUTLEN];
- char *cp;
- int c;
- int neg;
- int v;
- unsigned long id;
-
- /* CARE This algorithm does not null term the string ! */
-
- cp = &obuf[MAX_OUTLEN]; /* looks wrong, I know */
-
- neg = 0;
- if (i < 0)
- {
- if (base == 10)
- i = -i;
- else
- i = ~i;
- neg = 1;
- }
-
- for (c = 1; c < MAX_OUTLEN; c++)
- {
- id = n_ldiv(i, base);
- v = (int)((unsigned long)i - n_lmul(id, base));
- if (neg && base != 10)
- v = (~v) & (base - 1);
- i = id;
- *--cp = "0123456789ABCDEF"[v];
- if (i == 0)
- break;
- }
- if (neg && base == 10)
- n_putchar('-');
- while (c > 0)
- {
- n_putchar(*cp++);
- c--;
- }
- }
-
- #define STATE_NONE 0
- #define STATE_PERCENT 1
-
- void
- n_printf(char *format, ...)
- {
- int far *ap;
- char *str;
- char far *lstr;
- char c;
- int islong;
- int state;
-
- ap = MK_FP(segss(), (&format));
- ap++;
-
- state = STATE_NONE;
-
- for (; *format != '\0'; format++)
- {
- c = *format;
- switch (state)
- {
- case STATE_NONE:
- switch (c)
- {
- case '%':
- state = STATE_PERCENT;
- islong = 0;
- break;
- case '\n':
- n_putchar('\r');
- /* FALL THROUGH */
- default:
- n_putchar(*format);
- break;
- }
- break;
-
- case STATE_PERCENT:
- switch (c)
- {
- case 'l':
- islong = 1;
- continue;
- case 'd':
- case 'u':
- case 'x':
- case 'o':
- pnum(islong ? *(long far *) ap :
- (long) *(unsigned int far *) ap,
- c == 'o' ? 8 : (c == 'x' ? 16 : 10));
- if (islong)
- ap++;
- break;
- case 'p':
- if (islong)
- {
- pnum((long) *(unsigned int far *) (ap + 1), 16);
- n_putchar(':');
- }
- pnum((long) *(unsigned int far *) ap, 16);
- if (islong)
- ap++;
- break;
- case 's':
- if (islong)
- {
- /* special far string extension */
- for (lstr = *(char far * far *)ap; *lstr; lstr++)
- n_putchar(*lstr);
- if (islong)
- ap++;
- }
- else
- {
- /* string should not be on stack if SS!=DS */
- for (str = (char *) *ap; *str; str++)
- n_putchar(*str);
- }
- break;
- case 'c':
- n_putchar(c);
- break;
- default:
- n_putchar(c);
- break;
- }
- state = STATE_NONE;
- ap++;
- break;
- }
- }
- }
-
- static char name[128];
-
- int
- do_boot_process(char *ifname)
- {
- int result;
-
- n_printf("bootp protocol.\n");
- name[0] = '\0';
- /* initbootname(name, &nnmyaddr[1]); */
- startrand(nnmyaddr[4] ^ (short)n_ticks());
- if (monitor_check() > 1)
- return 1;
- init(ifname);
- if (debug)
- {
- n_printf("\nds %x cs %x ss %x, sp %x, start_of_data %x, end_of_data %x, end_of_bss %x\n",
- segds(), segcs(), segss(), &result, &start_of_data, &end_of_data,&end_of_bss);
-
- n_printf("You have %lx mem\n", n_lmul(n_mamount(), 1024));
- }
- result = bootp(name, sizeof(name));
- n_printf("\r");
- if (result)
- {
- netposterr(result);
- dlayershut();
- return 1;
- }
- n_printf("Local ip %d.%d.%d.%d. Server: ip %d.%d.%d.%d, Ethernet %x:%x:%x:%x:%x:%x\n",
- nnipnum[0], nnipnum[1], nnipnum[2], nnipnum[3],
- nnipserver[0], nnipserver[1], nnipserver[2], nnipserver[3],
- nnserveraddr[0], nnserveraddr[1], nnserveraddr[2], nnserveraddr[3], nnserveraddr[4], nnserveraddr[5]);
- udp_reinit();
- n_printf("tftp get %s.\n", name);
- result = tftp_get(name);
- if (result)
- {
- netposterr(result);
- dlayershut();
- return 1;
- }
- dlayershut();
- warp_speed_Mr_spock(); /* and they never saw him again */
- return 0;
- }
-
- int
- monitor_check()
- {
- int c;
-
- while (n_kbhit())
- {
- c = n_getch();
- if (c == 0x3 || c == 'x' || c == 'X')
- return 2;
- if (c == 'd' || c == 'D')
- debug = debug ? 0 : 1;
- }
- return 0;
- }
-
-
-