Re: BOOTP vendor support

Drew Daniel Perkins (
Sun, 7 Aug 88 01:24:30 -0400 (EDT)

> *Excerpts from 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'.


 * 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);
    if (p->p_flag&P_TRACE) {
        printf("BOOTP (%d):\r\n", p->p_len);
#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,
            } 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 */

        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 */

            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);

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 */

This archive was generated by hypermail 2.0b3 on Thu Mar 09 2000 - 14:43:12 GMT