home *** CD-ROM | disk | FTP | other *** search
- /*
- * BOOTP
- * Bootp Routines
- *
- ****************************************************************************
- * Originally *
- * part of: *
- * TCP/IP kernel for NCSA Telnet *
- * by Tim Krauskopf *
- * *
- * National Center for Supercomputing Applications *
- * 152 Computing Applications Building *
- * 605 E. Springfield Ave. *
- * Champaign, IL 61820 *
- * *
- ****************************************************************************
- *
- * Modified Apr / May 1993 by Jamie Honan
- */
-
- #include "protocol.h"
- #include "bootinc.h"
- #include "bootp.h"
-
- /*
- * Bootp routines : from the Clarkson 2.2 version of NCSA Telnet.
- * Thanks to Brad Clements for implementing this!
- *
- * bootp routines - These routines are based on the stanford/clarkson
- * bootp code. Originally developed at Stanford University.
- *
- * Bootp is a UDP based protocol that determines the clients IP address and
- * gateway information etc.
- */
-
- static struct bootp bootpacket;
- static u_long bootp_xid;
-
- /* sends a bootp broadcast packet */
- /* this routine does not do the initial setup of the bootp packet */
-
- static int
- sendbootp(void)
- {
- return (netusend(broadip, broadaddr, IPPORT_BOOTPS, IPPORT_BOOTPC, (unsigned char *) &bootpacket, (int) sizeof(struct bootp)));
- }
-
- /* initialize the bootp packet */
- static void
- bootp_init(char *name)
- {
- bootp_xid = n_ticks(); /* get a unique transaction ID */
- memset((char *) &bootpacket, 0, sizeof(bootpacket));
- bootpacket.bp_op = BOOTREQUEST;
- bootpacket.bp_htype = 1; /* hardware type 1 is ethernet. This
- * should be made more robust. */
- bootpacket.bp_hlen = sizeof(nnmyaddr);
- bootpacket.bp_xid = bootp_xid;
- bootpacket.bp_secs = 1;
- strncpy(bootpacket.bp_file, name, sizeof(bootpacket.bp_file) - 1);
- /* boot file name */
- memcpy(bootpacket.bp_chaddr, nnmyaddr, sizeof(nnmyaddr));
- }
-
- /* parse an incoming bootp packet */
- static int
- parse_bootpacket(struct bootp * bp)
- {
- unsigned char *c;
-
- memcpy(nnipnum, &bp->bp_yiaddr, 4);
- memcpy(nnipserver, &bp->bp_siaddr, 4);
- if (!memcmp(bp->bp_vend, VM_RFC1048, 4))
- {
- c = bp->bp_vend + 4;
- while ((*c != 255) && ((c - bp->bp_vend) < 64))
- {
- switch (*c)
- {
- case 0: /* nop pad */
- c++;
- break;
-
- case 1: /* subnet mask */
- c += *(c + 1) + 2;
- break;
-
- case 2: /* time offset */
- c += *(c + 1) + 2;
- break;
-
- case 3: /* gateways */
- c += *(c + 1) + 2;
- break;
-
- case 4: /* time servers */
- case 5: /* IEN=116 name server */
- c += *(c + 1) + 2;
- break;
-
- case 6: /* domain name server */
- c += *(c + 1) + 2;
- break;
-
- case 7: /* log server */
- case 8: /* cookie server */
- case 9: /* lpr server */
- case 10: /* impress server */
- case 11: /* rlp server */
- c += *(c + 1) + 2;
- break;
-
- case 12: /* client host name */
- c += *(c + 1) + 2;
- break;
-
- case 255:
- break;
-
- default:
- c += *(c + 1) + 2;
- break;
- }
- }
- }
- return (0);
- }
-
- /*
- * main processing of bootp lookup request calls
- * sendbootp to send a bootp request,
- * sets up the udp listen port etc, handles retries
- */
-
- int
- bootp(char *name, int namelen)
- {
- int x,
- y,
- delay;
- u_long start_time;
- struct bootp *bp;
- int ulen;
- int mask;
-
- bootp_init(name);
-
- bp = (struct bootp *) (&udp_rxdata.data);
- while ((ulen = udprecv(&udp_rxdata, IPPORT_BOOTPC)) != 0)
- {
- if (ulen < 0)
- return -ulen;
- }
- for (x = 0, mask = 1; x < BOOTP_RETRIES; x++)
- {
- if (debug)
- {
- n_printf("Bootp attempt %d\n", x+ 1);
- }
- else
- n_printf(".");
- if ((y = sendbootp()) != 0)
- { /* do some error processing */
- return (y);
- }
-
- start_time = n_secs();
- delay = random(mask) + 1;
- do
- {
- if (monitor_check() > 1)
- return 2000;
- ulen = udprecv(&udp_rxdata, IPPORT_BOOTPC);
- if (ulen)
- {
- if (ulen < 0)
- return -ulen;
- delay = 0;
- break;
- }
- }
- while ((n_secs() - start_time) < (long) delay);
- /* This implements the mask shifting recommended in RFC 1048 */
- if (mask < 127)
- mask = (mask << 1) | 1;
- if (delay)
- continue; /* time ran out and got nothing */
- if (((bp->bp_xid) == bootp_xid) &&
- ((bp->bp_op) == BOOTREPLY) &&
- (!memcmp(bp->bp_chaddr, nnmyaddr, sizeof(nnmyaddr))))
- break; /* got a valid reply */
- }
- if (x == BOOTP_RETRIES)
- { /* do some error processing */
- /* no response error number */
- return (1000);
- }
- if (parse_bootpacket(bp))
- return (1001);
- strncpy(name, bp->bp_file, namelen - 1);
- name[namelen - 1] = '\0';
- memcpy(nnserveraddr, udp_rxdata.d.me, DADDLEN);
- return (0);
- }
-
-