[comp.protocols.tcp-ip] BOOTP vendor support

root@sbcs.sunysb.edu (root) (08/02/88)

I am in the midst of implementing network bootstrap code for
our Amiga NFS product.  I have the new Sun bootparams bootstrapper
stuff going, but it seems to fall short of what is really needed.
In particular we're a bit worried that Sun requires use of RARP
in bootstrapping and that casual perusal of vendor glossies shows
not much support for RARP by vendors other than Sun (and NFS licensees).  

BOOTP seems to be a whole notch better in the sense that it is
a simpler protocol, it supplies HDW -> Internet address translation
without using RARP, and using the vendor specific field (RFC-1048)
seems to provide everything a booting machine needs eg subnet mask,
UTC time offset, name server locn, etc.  Since BOOTP doesn't use
RARP we can provide portable source to our customers who do not 
have it.  Now, the question: who else is/will support BOOTP?  The
only other vendor I've seen supporting BOOTP is SGI.  Is BOOTP
a dead end in light of Sun ASI, etc?

While I've got your attention, is anyone aware of any efforts towards
automating IP address generation?  It would seem a natural extentsion
to either RARP or BOOTP, modulo the usual database consistency 
problems.

					Rick Spanbauer
					Ameristar

hedrick@athos.rutgers.edu (Charles Hedrick) (08/05/88)

The only vendor that I know uses bootp is cisco.  Their gateways can
use it to get IP addresses.  (They can also use RARP - they send both
types of request, and believe whichever response they hear.)  They
also have the code needed to pass bootp requests across gateways.
I've never understood why other vendors don't use it, since it's
clearly easier to install than RARP, and more general.  I've not had
any trouble bringing up bootp on Unix systems, and it should also be
possible on Unix-based stuff like TWG's IP for VMS.  I'd be inclined
to use bootp anyway for any new products.

alan@cunixc.columbia.edu (Alan Crosswell) (08/05/88)

Cisco's bootp also works on the terminal server in SLIP mode.  I've
used the CMU PCIP distribution with it and it worked first time.  No
more custom netdev on 8 million PC's.
/a

dnwcv@dcatla.UUCP (William C. VerSteeg) (08/05/88)

I agree with the opinion that BOOTP is a good way to initialize a dumb
device. We at Digital Communication Associates are designing new products
that use BOOTP and TFTP to downline load code and configurations. A 
manufacturer of communications equipment has a great deal of impetous
to support these protocols. He requires them to boot. We will support 
BOOTP on both our large, disk based systems and our small diskless units.
In a typical configuration, the dumb devices will boot from the disk-based
units. When a customer wants only the smaller, cheaper units, they will have 
to boot from another vendor's device.

I am curious whether the minicomputer-oriented vendors will include support 
for BOOTP in their standard distributions. TWG, SRI, NRC, etc would be
well served by including as much functionality as possible. However, 
I wonder if the minicomputer manufacturers will be as likely to support
a protocol to load generic hardware. Would they fear selling fewer units
of there own diskless stations and terminal servers ? I also would like to
know of other BOOTP implementations to test against. 

Bill VerSteeg
DCA

dab@ALLSPICE.LCS.MIT.EDU (08/05/88)

Not exactly a vendor, but the MIT uVAX C-Gateway also uses bootp, not only
to find out its IP address but also to invoke TFTP to boot the gateway
code.  The gateway code also has the ability to forward bootp requests
through to appropriate bootp servers if necessary.  With the one exception
that the boot code had to be specific to a subnet (because the 4.2 servers
would only recognize broadcast addreses of the form net.subnet.0) bootp
has worked very well.

Also, CMU has been using bootp to auto-configure IBM PC's for quite a while
using the bootp vendor field to set the various other things the PC's need
to know.  [Now for the vendor support part] We'll be including a bootp
client for configuring PC's using the CMU style vendor field (actually
either CMU style or RFC-1048) with our next release.

						David Bridgham
						FTP Software

davidc@TERMINUS.UMD.EDU (David R. Conrad) (08/06/88)

Add the University of Maryland to the list of Universities that use
bootp for PCs.  Our public workstation labs use it with RFC1048
extensions to provide information for the TCP/IP for the PC that we use
here.  We currently use a bootp server per subnet so we don't have to
worry about gateways forwarding requests although our bootp server
(based on CMU's with local additions) does have forwarding capabilities. 
We'd also be interested in having more vendors (particularly Proteon)
support bootp forwarding

-drc

ddp+@ANDREW.CMU.EDU (Drew Daniel Perkins) (08/07/88)

> *Excerpts from ext.in.tcp-ip: 5-Aug-88 Re: BOOTP vendor support David R.*
> *Conrad@terminus (517)*

> We'd also be interested in having more vendors (particularly Proteon)
> support bootp forwarding

Hear Hear!  We find BOOTP very useful.  It's biggest problem though is that it
requires special support in gateways to forward requests across subnets.
Either that or a server for every subnet, which is a real pain since it is
often cost prohibitive.  As a campus support organization we can't afford to
put a server machine (or two for redundancy) on each net.  From my experience,
it takes less than 150 lines of code or so for a fairly robust gateway
forwarder implementation.  In case it helps anybody, here is most of the code
from our router implementation.  Everyone's router is different of course, so I
doubt if it will 'just slip in'.

Drew

/*
 * Bootstrap Protocol (BOOTP).  RFC 951.
 *
 * 07-Oct-86  Drew D. Perkins (ddp) at Carnegie-Mellon University
 *      Started history.
 *
 **********************************************************************
 */

#include "cond/bootp.h"

#if     C_BOOTP > 0

/*
 *  bp_input - process an incoming BOOTP server packet.
 *
 *  dv    = the device supplying the packet
 *  p     = the supplied BOOTP packet (with offset and length adjusted to
 *          remove any encapsulating headers/trailers)
 *  sport = the UDP source port of the sender of the datagram
 *  saddr = the datagram's IP source address
 *  daddr = the datagram's IP destination address
 *          (These will typically be pointers into the encapsulating IP
 *          header preceding the RCP packet - beware!)
 *
 *  The following consistency checks are performed on the BOOTP packet:
 *  - the physical length of the packet must be large enough to contain a
 *    minimal BOOTP header.
 *  If the packet is a boot request:
 *  - the packet must not have been through too many gateways.
 *  - the requestor must have waited a long enough time for service.
 *  If the packet checks out, the message is counted and processed
 *  according to the protocol.
 */

void bp_input(dv, p, sport, saddr, daddr)

  struct device      *dv;
  struct packet      *p;
         short        sport;
  struct socket p_pkt saddr;
  struct socket p_pkt daddr;

{
    register struct bootp p_pkt bp;
    register struct device *dvt;        /* determined target device of pkt */
    register struct ipmap *im;          /* IP routing table entry */
    register struct addmap *am;         /* ARP routing table entry */
    struct socket src, dest, tmp;       /* src and dest of outgoing IP pkt */
    short dport;                        /* destination UDP port */
    int flag = 0;                       /* Have seen incoming device flag */

    if (p->p_len < BOOTHEAD) {  /* Packet large enough? */
        profile(dv, bp_rmin);
        errorlog(p, EL_BP_RMIN);
        goto out;
    }

    bp = poff(bootp, p);
#ifdef BOOTPDEBUG
    if (p->p_flag&P_TRACE) {
        printf("BOOTP (%d):\r\n", p->p_len);
        bp_prt(bp);
    }
#endif  /* BOOTPDEBUG */

    switch(bp->bp_op) {         /* Check opcode */
        case BOOTREQUEST:
                                /* Only forward after some amount time */
            if (ntohs(bp->bp_secs) < BOOTMINSECS) {
                profile(dv, bp_rsecs);
                goto out;
            }
                                /* Prevent loops */
            if (bp->bp_hops++ > BOOTMAXHOPS) {
                profile(dv, bp_rhops);
                errorlog(p, EL_BP_RHOPS);
                goto out;
            }
            for (dvt=dv; flag == 0 || dvt != dv; dvt=dvt->dv_prnext[PR_IP]) {
                flag = 1;
                bcopy((char *)&dvt->dv_praddr[PRA_IP],(char *)&tmp, PRL_IP);
                if (bp->bp_giaddr.s_addr == tmp.s_addr) {
                    profile(dv, bp_rloop);
                    errorlog(p, EL_BP_RLOOP);
                    goto out;
                }
            }

            profile(dv, bp_reqcnt);

                                /* Fill in gateway field if empty */
            if (!bp->bp_giaddr.s_addr) {
                copout(&dv->dv_praddr[PRA_IP], (char p_pkt) &bp->bp_giaddr,
                                PRL_IP);
            } else {
                profile(dv, bp_rgway);
            }

            src.s_addr = bp->bp_giaddr.s_addr;
            dest.s_addr = daddr->s_addr;

                                /* Check out destination address */
            am = ar_map(PR_IP, (char p_pkt)daddr);
            if (am == 0 || !(am->am_flag&AM_BCAST)) {
                dest.s_addr = ipaddr(0xff, 0xff, 0xff, 0xff);
                profile(dv, bp_rbaddst);
            }

            dport = UD_BOOTPS;  /* Send to BOOTP Server */
            break;

        case BOOTREPLY:
            if (!bp->bp_yiaddr.s_addr) {
                profile(dv, bp_runkaddr);
                errorlog(p, EL_BP_RUNKADDR);
                goto out;
            }

            profile(dv, bp_repcnt);
            dest.s_addr = bp->bp_yiaddr.s_addr;
                                /* Set up arp cache */
            im = im_map(daddr, IM_ME);
                        /* If it isn't found then we got this by mistake */
            if (im == 0) {
                goto out;
            }
            dvt = im->im_dv;
            ar_remap(PR_IP,(char p_pkt)&dest,(char p_pkt)bp->bp_chaddr, dvt);
            src.s_addr = saddr->s_addr;
            dport = UD_BOOTPC;  /* Send to BOOTP client */
            break;

        default:
            profile(dv, bp_rbadop);
            errorlog(p, EL_BP_ROP);
            goto out;
    }

    ud_output(dv, p, sport, dport, (struct socket p_pkt) &dest,
                                        (struct socket p_pkt) &src);
    return;
out:
    (*(p->p_done))(p);
}


void bp_prt(bp)
register struct bootp p_pkt bp;
{
    char tempa[20],tempb[20],tempc[20],tempd[20];
    int i;

    printf("    op: %d, hops %d, id %ld, secs %d\r\n",
        bp->bp_op, bp->bp_hops, bp->bp_xid, bp->bp_secs);
    printf("    htype %d, hlen %d, chaddr ",
        bp->bp_htype, bp->bp_hlen);
    for (i = 0; i < bp->bp_hlen; i++)
        printf("%2x", bp->bp_chaddr[i]);
    printf("\r\n    ciaddr = %s, yiaddr = %s, siaddr = %s, giaddr = %s\r\n",
        ip_fmt(&bp->bp_ciaddr, tempa),
        ip_fmt(&bp->bp_yiaddr, tempb),
        ip_fmt(&bp->bp_siaddr, tempc),
        ip_fmt(&bp->bp_giaddr, tempd));
}
#endif  /* C_BOOTP */