Path: utzoo!attcan!uunet!husc6!rutgers!ucsd!ucbvax!ANDREW.CMU.EDU!ddp+ From: ddp+@ANDREW.CMU.EDU (Drew Daniel Perkins) Newsgroups: comp.protocols.tcp-ip Subject: Re: BOOTP vendor support Message-ID: <4WyyaCy00UoJ84l4tG@andrew.cmu.edu> Date: 7 Aug 88 05:24:30 GMT References: <8808060148.AA08190@terminus.UMD.EDU> Sender: daemon@ucbvax.BERKELEY.EDU Organization: The Internet Lines: 184 > *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 */