diff --git a/usr.sbin/bootp/bootpd/Announce b/usr.sbin/bootp/bootpd/Announce index 0eef65477528..e4ae04c20d84 100644 --- a/usr.sbin/bootp/bootpd/Announce +++ b/usr.sbin/bootp/bootpd/Announce @@ -4,7 +4,7 @@ from the original BOOTP server created by Bill Croft at Stanford. This version merges most of the enhancements and bug-fixes from the NetBSD, Columbia, and other versions. -New features: +New features in version 2.4 include: Added a simple BOOTP gateway program: bootpgw Allow host name anywhere IP address is expected. @@ -25,8 +25,10 @@ New features: Added RFC 1533 tags 40,41,42 :yd=:ys=:nt=: ConvOldTab.sh to convert old (1.1) bootptab to new format. + Permits extended-length replies with more option data. + +Problems fixed in this version: -Fixes included: Fixed references to free host structures. (used to cause core dump on Solaris) Remove change that added null terminator to string options. @@ -50,9 +52,12 @@ Systems on which I have seen this code work: Systems on which others say this code works: CDC EP/IX (1.4.3, 2.1.1) DEC Ultrix (4.2, 4.3) - NetBSD (Current-1/94) + NetBSD (Current-8/94) OSF/1 (DEC Alpha CPU) +Please direct questions, comments, and bug reports to: + + Gordon W. Ross Mercury Computer Systems gwr@mc.com 199 Riverneck Road 508-256-1300 Chelmsford, MA 01824-2820 diff --git a/usr.sbin/bootp/bootpd/Announce.old b/usr.sbin/bootp/bootpd/Announce.old new file mode 100644 index 000000000000..c78e3926c987 --- /dev/null +++ b/usr.sbin/bootp/bootpd/Announce.old @@ -0,0 +1,141 @@ + +[ Old announcement from version 2.2: ] + +New features in version 2.2 include: + +o A new "td" tag allows the specification of a "TFTP directory" for use + with so-called "secure" implementations of tftpd which chroot(2) to a + particular directory. + +o A new "sa" tag allows the explicit specification of the TFTP + "server address." Formerly, the 'siaddr' field of the BOOTREPLY was + always filled with the IP address of the BOOTP server. The "sa" tag + now allows the BOOTP server and the TFTP server to be two different + machines, if desired. + +o The server now automatically determines whether it is running as a + standalone program (e.g. invoked by hand from a shell) or as a child of + /etc/inetd. The -s option and a new -i option are provided to force + standalone or inetd mode if necessary. + +o When the vendor magic cookie is zero, BOOTP replies now default to the + RFC 1084 vendor format, rather than the old CMU format. This helps + interoperability with uncooperative BOOTP clients which want RFC 1084 + format but don't bother filling in the magic cookie properly to tell + the server... *sigh* (This makes the ":vm=rfc1048:" tag unnecessary + in most cases now. Oh, the "vm" tag now accepts "rfc1084" as well as + "rfc1048" -- they mean the same thing.) + +o Log messages now include the specific network type. For example, rather + than saying "request from hardware address ABCDEF012345", the message is + now "request from Ethernet address ABCEDF012345", or "request from + IEEE802 address 4000A1B2C3D4". + + +Bug fixes in this version include: + +o The automatic bootfile-size calculation now works correctly when the + file size is an exact multiple of 512 octets. It used to return a number + which was one 512-octet unit greater than necessary. + +o A bug in comparing subnet masks has been fixed. + +o A bug in calculating the size of the vendor information area when + inserting the hostname has been fixed. + + +Other changes: + +o The man page has been split into two man pages. One covers the server + itself (bootpd.8) and the other covers the configuration file format + (bootptab.5). + + +[ Old announcement from version 2.1: ] + +Subject: Updated RFC1048 BOOTP server now available + +Well, no surprise, bootpd 2.0 had a few bugs. A new improved version, +bootpd 2.1, is now available for anonymous FTP from lancaster.andrew.cmu.edu +(128.2.13.21). The new server can be found in pub/bootp.2.1.tar. + +Bug fixes and improvements in version 2.1 include: + +o The definition of "access to the bootfile" has been changed to require the + public read access bit to be set. This is required by tftpd(8), so the + server will not reply with a file which a client cannot obtain via TFTP. +o The RFC1084 bootfile size tag has been implemented. It allows either + automatic or manual specification of the bootfile size in 512-octet blocks. +o Generic tags now work as advertised. +o A subtle bug which caused strange parsing behavior under certain conditions + has been fixed. +o The RFC1048 vendor information now has the correct byte order on + little-endien machines such as the VAX. +o Failure to specify the bootfile home directory and/or default bootfile in + the configuration file no longer causes server crashes. The server now + makes a reasonably intelligent choice if this configuration information is + missing. This is documented in the man page. +o BOOTP requests from clients which already know their IP addresses no longer + cause server crashes. + + +Please direct questions, comments, and bug reports to +Walt Wimer or Drew Perkins . +[ Changed: now please send mail to: ] + + +Good luck, + +Walt Wimer +Network Development +Carnegie Mellon University + + +[ Old announcement from version 2.0: ] + +Subject: RFC-1048 compatible BOOTP server now available + + +An RFC-1048 (BOOTP Vendor Information Extensions) compatible BOOTP (RFC-951) +server is now available for anonymous FTP from lancaster.andrew.cmu.edu +(128.2.13.21). The new server can be found in pub/bootp.2.0.tar. This is +an enhanced version of the existing CMU BOOTP server which was derived from +the original BOOTP server created by Bill Croft at Stanford. + +New features and changes in version 2.0 include: + +o Full support for the vendor information extensions described in RFC-1048. +o Faster response time (host lookup via hash table instead of linear search). +o New termcap-like configuration file format which allows greater flexibility + in specifying the variable vendor information of RFC-1048. Host entries + may refer to other hosts as templates so that redundant information need + be specified only once. +o Continued support for the CMU vendor information format. The server may + be configured on a per-host basis to always reply with a certain vendor + information format or to reply based on the client's request. +o Expanded logging. +o The server may now be run by inetd or as a standalone program like the + old version. +o The configuration and debugging dump files may be specified on the command + line. + + +The server has been successfully tested on the following machines: + + IBM RT PC running ACIS 4.3 (4.3 BSD) + Sun 3/50 running SunOS 3.5 + DEC MicroVAX II running Ultrix 1.1 + DEC MicroVAX II running Ultrix 2.2 + + +Please direct questions, comments, and bug reports to +Walt Wimer or Drew Perkins . +[ Changed: now please send mail to: ] + + +Sincerely, + +Walt Wimer +Network Development +Carnegie Mellon University + diff --git a/usr.sbin/bootp/bootpd/Changes b/usr.sbin/bootp/bootpd/Changes index 222cb8936b84..06165486acc5 100644 --- a/usr.sbin/bootp/bootpd/Changes +++ b/usr.sbin/bootp/bootpd/Changes @@ -2,6 +2,20 @@ Changes, most recent first Date, Real Name what... +--> bootp-2.4.0 + +08/20/94 gwr@mc.com (Gordon W. Ross) + Fix code to build bootfile name based on combination of + client requested name and bootfile specifications. + Behave similarly with or without CHECK_FILE_ACCESS. + +07/30/94 Dirk Koeppen + Add "min wait" option (mw) to cause bootpd to ignore + requests from clients that have not waited long enough. + Add code to honor client requests containing the DHCP + option "Maximum Message Size" and use its value to + determine the size of the reply message. + --> bootp-2.3.8 06/25/94 Christos Zoulas diff --git a/usr.sbin/bootp/bootpd/Makefile.UNIX b/usr.sbin/bootp/bootpd/Makefile.UNIX index 3d6bc547dd9e..e333ce5d2ca8 100644 --- a/usr.sbin/bootp/bootpd/Makefile.UNIX +++ b/usr.sbin/bootp/bootpd/Makefile.UNIX @@ -138,9 +138,6 @@ OBJ_TEST= bootptest.o print-bootp.o getif.o getether.o \ bootptest: $(OBJ_TEST) $(CC) -o $@ $(OBJ_TEST) $(SYSLIBS) -print-bootp.o : print-bootp.c - $(CC) $(CFLAGS) -DBOOTPTEST -c $< - # This is just for testing the lookup functions. TRYLOOK= trylook.o lookup.o report.o $(STRERROR) trylook : $(TRYLOOK) diff --git a/usr.sbin/bootp/bootpd/README b/usr.sbin/bootp/bootpd/README index 88dd6f8fc486..c7755b786ddb 100644 --- a/usr.sbin/bootp/bootpd/README +++ b/usr.sbin/bootp/bootpd/README @@ -4,11 +4,9 @@ from the original BOOTP server created by Bill Croft at Stanford. This version merges all the enhancements and bug-fixes from the NetBSD, Columbia, and other versions. -If you have problems or questions about this version, send email to: - gwr@mc.com (Gordon W. Ross) +Please direct questions, comments, and bug reports to the list: + -For general questions about BOOTP, send email to the list: - bootp@andrew.cmu.edu You can subscribe to this mailing list by sending mail to: bootp-request@andrew.cmu.edu (The body of the message should contain: "Add ") @@ -91,9 +89,11 @@ Pittsburgh, PA 15213 [ Contents description by file: ] Announce* Text of release announcements +Changes Change history, reverse chronological Installation Instructions for building and installing Makefile* for "make" README This file +ToDo Things not yet done bootp.h The protocol header file bootpd.8 Manual page for bootpd, boopgw bootpd.c BOOTP server main module diff --git a/usr.sbin/bootp/bootpd/bootpd.8 b/usr.sbin/bootp/bootpd/bootpd.8 index 19b8837f300a..4a452bd1f761 100644 --- a/usr.sbin/bootp/bootpd/bootpd.8 +++ b/usr.sbin/bootp/bootpd/bootpd.8 @@ -1,6 +1,6 @@ .\" Copyright (c) 1988, 1989, 1991 Carnegie Mellon University .\" -.\" $Header: /cvsroot/src/usr.sbin/bootp/bootpd/bootpd.8,v 1.1.1.1 1994/06/27 21:25:48 gwr Exp $ +.\" $Header: /cvsroot/src/usr.sbin/bootp/bootpd/bootpd.8,v 1.2 1994/08/22 22:14:41 gwr Exp $ .\" .TH BOOTPD 8 "November 06, 1993" "Carnegie Mellon University" .SH NAME diff --git a/usr.sbin/bootp/bootpd/bootpd.c b/usr.sbin/bootp/bootpd/bootpd.c index 4ca3033c3037..cdd042c3d497 100644 --- a/usr.sbin/bootp/bootpd/bootpd.c +++ b/usr.sbin/bootp/bootpd/bootpd.c @@ -21,7 +21,7 @@ SOFTWARE. ************************************************************************/ #ifndef lint -static char rcsid[] = "$Id: bootpd.c,v 1.1.1.1 1994/06/27 21:25:49 gwr Exp $"; +static char rcsid[] = "$Id: bootpd.c,v 1.2 1994/08/22 22:14:43 gwr Exp $"; #endif /* @@ -95,9 +95,6 @@ static char rcsid[] = "$Id: bootpd.c,v 1.1.1.1 1994/06/27 21:25:49 gwr Exp $"; #include "tzone.h" #include "patchlevel.h" -/* Local definitions: */ -#define MAXPKT (3*512) /* Maximum packet size */ - #ifndef CONFIG_FILE #define CONFIG_FILE "/etc/bootptab" #endif @@ -220,7 +217,7 @@ main(argc, argv) assert(sizeof(struct bootp) == BP_MINPKTSZ); /* Get space for receiving packets and composing replies. */ - pktbuf = malloc(MAXPKT); + pktbuf = malloc(MAX_MSG_SIZE); if (!pktbuf) { report(LOG_ERR, "malloc failed"); exit(1); @@ -524,7 +521,7 @@ main(argc, argv) exit(0); } ra_len = sizeof(recv_addr); - n = recvfrom(s, pktbuf, MAXPKT, 0, + n = recvfrom(s, pktbuf, MAX_MSG_SIZE, 0, (struct sockaddr *) &recv_addr, &ra_len); if (n <= 0) { continue; @@ -612,11 +609,10 @@ handle_request() int32 bootsize = 0; unsigned hlen, hashcode; int32 dest; -#ifdef CHECK_FILE_ACCESS char realpath[1024]; - char *path; + char *clntpath; + char *homedir, *bootfile; int n; -#endif /* XXX - SLIP init: Set bp_ciaddr = recv_addr here? */ @@ -639,6 +635,7 @@ ignoring request for server %s from client at %s address %s", strcpy(bp->bp_sname, hostname); } + /* Convert the request into a reply. */ bp->bp_op = BOOTREPLY; if (bp->bp_ciaddr.s_addr == 0) { /* @@ -714,6 +711,21 @@ HW addr type is IEEE 802. convert to %s and check again\n", hp->hostname->string); } + /* + * If there is a response delay threshold, ignore requests + * with a timestamp lower than the threshold. + */ + if (hp->flags.min_wait) { + u_int32 t = (u_int32) ntohs(bp->bp_secs); + if (t < hp->min_wait) { + if (debug > 1) + report(LOG_INFO, + "ignoring request due to timestamp (%d < %d)", + t, hp->min_wait); + return; + } + } + #ifdef YORK_EX_OPTION /* * The need for the "ex" tag arose out of the need to empty @@ -785,163 +797,125 @@ HW addr type is IEEE 802. convert to %s and check again\n", */ /* - * XXX - I think the above policy is too complicated. When the - * boot file is missing, it is not obvious why bootpd will not - * respond to client requests. Define CHECK_FILE_ACCESS if you - * want the original complicated policy, otherwise bootpd will - * no longer check for existence of the boot file. -gwr + * XXX - I don't like the policy of ignoring a client when the + * boot file is not accessible. The TFTP server might not be + * running on the same machine as the BOOTP server, in which + * case checking accessibility of the boot file is pointless. + * + * Therefore, file accessibility is now demanded ONLY if you + * define CHECK_FILE_ACCESS in the Makefile options. -gwr */ -#ifdef CHECK_FILE_ACCESS - + /* + * The "real" path is as seen by the BOOTP daemon on this + * machine, while the client path is relative to the TFTP + * daemon chroot directory (i.e. /tftpboot). + */ if (hp->flags.tftpdir) { strcpy(realpath, hp->tftpdir->string); - path = &realpath[strlen(realpath)]; + clntpath = &realpath[strlen(realpath)]; } else { - path = realpath; + clntpath = realpath; } + /* + * Determine client's requested homedir and bootfile. + */ + homedir = NULL; + bootfile = NULL; if (bp->bp_file[0]) { - /* - * The client specified a file. - */ - if (bp->bp_file[0] == '/') { - strcpy(path, bp->bp_file); /* Absolute pathname */ + homedir = bp->bp_file; + bootfile = strrchr(homedir, '/'); + if (bootfile) { + if (homedir == bootfile) + homedir = NULL; + *bootfile++ = '\0'; } else { - if (hp->flags.homedir) { - strcpy(path, hp->homedir->string); - strcat(path, "/"); - strcat(path, bp->bp_file); - } else { - report(LOG_NOTICE, - "requested file \"%s\" not found: hd unspecified", - bp->bp_file); - return; - } + /* no "/" in the string */ + bootfile = homedir; + homedir = NULL; } - } else { - /* - * No file specified by the client. - */ - if (hp->flags.bootfile && ((hp->bootfile->string)[0] == '/')) { - strcpy(path, hp->bootfile->string); - } else if (hp->flags.homedir && hp->flags.bootfile) { - strcpy(path, hp->homedir->string); - strcat(path, "/"); - strcat(path, hp->bootfile->string); - } else { - bzero(bp->bp_file, sizeof(bp->bp_file)); - goto skip_file; /* Don't bother trying to access the file */ + if (debug > 2) { + report(LOG_INFO, "requested path=\"%s\" file=\"%s\"", + (homedir) ? homedir : "", + (bootfile) ? bootfile : ""); } } + /* + * Specifications in bootptab override client requested values. + */ + if (hp->flags.homedir) + homedir = hp->homedir->string; + if (hp->flags.bootfile) + bootfile = hp->bootfile->string; + + /* + * Construct bootfile path. + */ + if (homedir) { + if (homedir[0] != '/') + strcat(clntpath, "/"); + strcat(clntpath, homedir); + homedir = NULL; + } + if (bootfile) { + if (bootfile[0] != '/') + strcat(clntpath, "/"); + strcat(clntpath, bootfile); + bootfile = NULL; + } + /* * First try to find the file with a ".host" suffix */ - n = strlen(path); - strcat(path, "."); - strcat(path, hp->hostname->string); + n = strlen(clntpath); + strcat(clntpath, "."); + strcat(clntpath, hp->hostname->string); if (chk_access(realpath, &bootsize) < 0) { - path[n] = 0; /* Try it without the suffix */ + clntpath[n] = 0; /* Try it without the suffix */ if (chk_access(realpath, &bootsize) < 0) { + /* neither "file.host" nor "file" was found */ +#ifdef CHECK_FILE_ACCESS + if (bp->bp_file[0]) { /* * Client wanted specific file * and we didn't have it. */ report(LOG_NOTICE, - "requested file not found: \"%s\"", path); + "requested file not found: \"%s\"", clntpath); return; - } else { - /* - * Client didn't ask for a specific file and we couldn't - * access the default file, so just zero-out the bootfile - * field in the packet and continue processing the reply. - */ - bzero(bp->bp_file, sizeof(bp->bp_file)); - goto skip_file; } - } - } - strcpy(bp->bp_file, path); + /* + * Client didn't ask for a specific file and we couldn't + * access the default file, so just zero-out the bootfile + * field in the packet and continue processing the reply. + */ + bzero(bp->bp_file, sizeof(bp->bp_file)); + goto null_file_name; - skip_file: - ; - #else /* CHECK_FILE_ACCESS */ - /* - * This implements a simple response policy, where bootpd - * will fail to respond only if it knows nothing about - * the client that sent the request. This plugs in the - * boot file name but does not demand that it exist. - * - * If either the client or the server specifies a boot file, - * build the path name for it. Server boot file preferred. - */ - if (bp->bp_file[0] || hp->flags.bootfile) { - char requested_file[BP_FILE_LEN]; - char *given_file; - char *p = bp->bp_file; - int space = BP_FILE_LEN; - int n; + /* Complain only if boot file size was needed. */ + if (hp->flags.bootsize_auto) { + report(LOG_ERR, "can not determine size of file \"%s\"", + clntpath); + } - /* Save client's requested file name. */ - strncpy(requested_file, bp->bp_file, BP_FILE_LEN); - - /* If tftpdir is set, insert it. */ - if (hp->flags.tftpdir) { - n = strlen(hp->tftpdir->string); - if ((n+1) >= space) - goto nospc; - strcpy(p, hp->tftpdir->string); - p += n; - space -= n; - } - - /* If homedir is set, insert it. */ - if (hp->flags.homedir) { - n = strlen(hp->homedir->string); - if ((n+1) >= space) - goto nospc; - strcpy(p, hp->homedir->string); - p += n; - space -= n; - } - - /* Finally, append the boot file name. */ - if (hp->flags.bootfile) - given_file = hp->bootfile->string; - else - given_file = requested_file; - assert(given_file); - n = strlen(given_file); - if ((n+1) >= space) - goto nospc; - strcpy(p, given_file); - p += n; - space -= n; - *p = '\0'; - - if (space <= 0) { - nospc: - report(LOG_ERR, "boot file path too long (%s)", - hp->hostname->string); +#endif /* CHECK_FILE_ACCESS */ } } + strncpy(bp->bp_file, clntpath, BP_FILE_LEN); + if (debug > 2) + report(LOG_INFO, "bootfile=\"%s\"", clntpath); - /* Determine boot file size if requested. */ - if (hp->flags.bootsize_auto) { - if (bp->bp_file[0] == '\0' || - chk_access(bp->bp_file, &bootsize) < 0) - { - report(LOG_ERR, "can not determine boot file size for %s", - hp->hostname->string); - } - } +null_file_name: -#endif /* CHECK_FILE_ACCESS */ + /* + * Handle vendor options based on magic number. + */ if (debug > 1) { report(LOG_INFO, "vendor magic field is %d.%d.%d.%d", @@ -1018,12 +992,15 @@ sendreply(forward, dst_override) struct bootp *bp = (struct bootp *) pktbuf; struct in_addr dst; u_short port = bootpc_port; -#if 0 - u_char canon_haddr[MAXHADDRLEN]; -#endif unsigned char *ha; int len; + /* + * XXX - Should honor bp_flags "broadcast" bit here. + * Temporary workaround: use the :ra=ADDR: option to + * set the reply address to the broadcast address. + */ + /* * If the destination address was specified explicitly * (i.e. the broadcast address for HP compatiblity) @@ -1055,17 +1032,7 @@ sendreply(forward, dst_override) len = bp->bp_hlen; if (len > MAXHADDRLEN) len = MAXHADDRLEN; -#if 0 - /* - * XXX - Is this necessary, given that the HW address - * in bp_chaddr was left as the client provided it? - * Does some DEC version of TCP/IP need this? -gwr - */ - if (bp->bp_htype == HTYPE_IEEE802) { - haddr_conv802(ha, canon_haddr, len); - ha = canon_haddr; - } -#endif + if (debug > 1) report(LOG_INFO, "setarp %s - %s", inet_ntoa(dst), haddrtoa(ha, len)); @@ -1243,8 +1210,77 @@ dovend_rfc1048(bp, hp, bootsize) static char noroom[] = "%s: No room for \"%s\" option"; vp = bp->bp_vend; - bytesleft = sizeof(bp->bp_vend); /* Initial vendor area size */ - bcopy(vm_rfc1048, vp, 4); /* Copy in the magic cookie */ + + if (hp->flags.msg_size) { + pktlen = hp->msg_size; + } else { + /* + * If the request was longer than the official length, build + * a response of that same length where the additional length + * is assumed to be part of the bp_vend (options) area. + */ + if (pktlen > sizeof(*bp)) { + if (debug > 1) + report(LOG_INFO, "request message length=%d", pktlen); + } + /* + * Check whether the request contains the option: + * Maximum DHCP Message Size (RFC1533 sec. 9.8) + * and if so, override the response length with its value. + * This request must lie within the first BP_VEND_LEN + * bytes of the option space. + */ + { + byte *p, *ep; + byte tag, len; + short msgsz = 0; + + p = vp + 4; + ep = p + BP_VEND_LEN - 4; + while (p < ep) { + tag = *p++; + /* Check for tags with no data first. */ + if (tag == TAG_PAD) + continue; + if (tag == TAG_END) + break; + /* Now scan the length byte. */ + len = *p++; + switch (tag) { + case TAG_MAX_MSGSZ: + if (len == 2) { + bcopy(p, (char*)&msgsz, 2); + msgsz = ntohs(msgsz); + } + break; + case TAG_SUBNET_MASK: + /* XXX - Should preserve this if given... */ + break; + } /* swtich */ + p += len; + } + + if (msgsz > sizeof(*bp)) { + if (debug > 1) + report(LOG_INFO, "request has DHCP msglen=%d", msgsz); + pktlen = msgsz; + } + } + } + + if (pktlen < sizeof(*bp)) { + report(LOG_ERR, "invalid response length=%d", pktlen); + pktlen = sizeof(*bp); + } + bytesleft = ((byte*)bp + pktlen) - vp; + if (pktlen > sizeof(*bp)) { + if (debug > 1) + report(LOG_INFO, "extended reply, length=%d, options=%d", + pktlen, bytesleft); + } + + /* Copy in the magic cookie */ + bcopy(vm_rfc1048, vp, 4); vp += 4; bytesleft -= 4; diff --git a/usr.sbin/bootp/bootpd/bootptab.5 b/usr.sbin/bootp/bootpd/bootptab.5 index 71b6df97a022..a3bf3ccfe5c2 100644 --- a/usr.sbin/bootp/bootpd/bootptab.5 +++ b/usr.sbin/bootp/bootpd/bootptab.5 @@ -1,6 +1,6 @@ .\" Copyright (c) 1988, 1989, 1991 Carnegie Mellon University .\" -.\" $Header: /cvsroot/src/usr.sbin/bootp/bootpd/bootptab.5,v 1.1.1.1 1994/06/27 21:25:48 gwr Exp $ +.\" $Header: /cvsroot/src/usr.sbin/bootp/bootpd/bootptab.5,v 1.2 1994/08/22 22:14:51 gwr Exp $ .\" .TH BOOTPTAB 5 "October 31, 1991" "Carnegie Mellon University" .UC 6 diff --git a/usr.sbin/bootp/bootpd/bootptab.mcs b/usr.sbin/bootp/bootpd/bootptab.mcs index ea8296f8fd6d..6fa04d1347eb 100644 --- a/usr.sbin/bootp/bootpd/bootptab.mcs +++ b/usr.sbin/bootp/bootpd/bootptab.mcs @@ -41,9 +41,9 @@ # First, we define a global entry which specifies the stuff every host uses. -# If you leave "td" and "hd" unset, run bootpd with the "-c /tftpboot" -# switch so path names (boot files) will be interpreted relative to -# the same directory as tftpd will use as its CWD. +# If you leave "td" empty, run bootpd with the "-c /tftpboot" switch +# so path names (boot files) will be interpreted relative to the same +# directory as tftpd will use when opening files. .default:\ :hn:dn="mc.com":\ :td=/tftpboot:\ @@ -82,14 +82,11 @@ eps1: tc=.subnet16:ha=00.80.A3.04.1D.78: tp885: tc=.subnet17:ha=08.00.4C.00.2F.74:bf=tp885sys2.cfe: # MVME147 VxWorks board. -mvme147:tc=.subnet17:ha=08.00.3e.20.da.47:bf=mv147vxw.st: +#mvme147:tc=.subnet17:ha=08.00.3e.20.da.47:bf=mv147vxw.st: # These are just for testing -walnut:tc=.subnet16:ha=walnut:sa=merlin-gw:\ - :td@:hd=/export/walnut/: - -banana:tc=.subnet17:ha=banana:bf=boot.sun4c: -thor:tc=.subnet17:ha=thor:bf=boot.sun4e: - -classic: tc=.subnet16:ha=08.00.20.04.95.3E: +walnut:tc=.subnet16:ha=walnut: +banana:tc=.subnet17:ha=banana: +thor:tc=.subnet17:ha=thor: +classic:tc=.subnet16:ha=classic: diff --git a/usr.sbin/bootp/bootpef/bootpef.c b/usr.sbin/bootp/bootpef/bootpef.c index e3f17f18f6ba..4b2e3f405cde 100644 --- a/usr.sbin/bootp/bootpef/bootpef.c +++ b/usr.sbin/bootp/bootpef/bootpef.c @@ -21,7 +21,7 @@ SOFTWARE. ************************************************************************/ #ifndef lint -static char rcsid[] = "$Id: bootpef.c,v 1.1.1.1 1994/06/27 21:25:49 gwr Exp $"; +static char rcsid[] = "$Id: bootpef.c,v 1.2 1994/08/22 22:14:46 gwr Exp $"; #endif diff --git a/usr.sbin/bootp/bootpgw/bootpgw.c b/usr.sbin/bootp/bootpgw/bootpgw.c index 937a10b47d50..f157ccac9e85 100644 --- a/usr.sbin/bootp/bootpgw/bootpgw.c +++ b/usr.sbin/bootp/bootpgw/bootpgw.c @@ -26,7 +26,7 @@ SOFTWARE. ************************************************************************/ #ifndef lint -static char rcsid[] = "$Id: bootpgw.c,v 1.1.1.1 1994/06/27 21:25:51 gwr Exp $"; +static char rcsid[] = "$Id: bootpgw.c,v 1.2 1994/08/22 22:14:48 gwr Exp $"; #endif /* @@ -78,7 +78,7 @@ static char rcsid[] = "$Id: bootpgw.c,v 1.1.1.1 1994/06/27 21:25:51 gwr Exp $"; #include "patchlevel.h" /* Local definitions: */ -#define MAXPKT (3*512) /* Maximum packet size */ +#define MAX_MSG_SIZE (3*512) /* Maximum packet size */ #define TRUE 1 #define FALSE 0 #define get_network_errmsg get_errmsg @@ -184,7 +184,7 @@ main(argc, argv) assert(sizeof(struct bootp) == BP_MINPKTSZ); /* Get space for receiving packets and composing replies. */ - pktbuf = malloc(MAXPKT); + pktbuf = malloc(MAX_MSG_SIZE); if (!pktbuf) { report(LOG_ERR, "malloc failed"); exit(1); @@ -455,7 +455,7 @@ main(argc, argv) exit(0); } ra_len = sizeof(recv_addr); - n = recvfrom(s, pktbuf, MAXPKT, 0, + n = recvfrom(s, pktbuf, MAX_MSG_SIZE, 0, (struct sockaddr *) &recv_addr, &ra_len); if (n <= 0) { continue; diff --git a/usr.sbin/bootp/bootptest/bootptest.8 b/usr.sbin/bootp/bootptest/bootptest.8 index a564bcf0a337..d076c8bc25b6 100644 --- a/usr.sbin/bootp/bootptest/bootptest.8 +++ b/usr.sbin/bootp/bootptest/bootptest.8 @@ -6,8 +6,16 @@ bootptest \- send BOOTP queries and print responses .LP .B bootptest [ +.B \-f +.I bootfile +] +[ .B \-h ] +[ +.B \-m +.I magic_number +] .I server\-name .RI [ template-file ] .SH DESCRIPTION @@ -21,10 +29,20 @@ After a response is received, will wait one more second listening for additional responses. .SH OPTIONS .TP +.B \-f +.I bootfile +Fill in the boot file field of the request with +.IR bootfile . +.TP .B \-h Use the hardware (Ethernet) address to identify the client. By default, the IP address is copied into the request indicating that this client already knows its IP address. +.TP +.B \-m +.I magic_number +Initialize the first word of the vendor options field with +.IR magic_number . .LP A .I template-file diff --git a/usr.sbin/bootp/bootptest/bootptest.c b/usr.sbin/bootp/bootptest/bootptest.c index b288641232ef..bc235ac10650 100644 --- a/usr.sbin/bootp/bootptest/bootptest.c +++ b/usr.sbin/bootp/bootptest/bootptest.c @@ -5,9 +5,9 @@ * various places, including the CMU BOOTP client and server. * The packet printing routine is from the Berkeley "tcpdump" * program with some enhancements I added. The print-bootp.c - * file is shared with my copy of "tcpdump" and therefore uses + * file was shared with my copy of "tcpdump" and therefore uses * some unusual utility routines that would normally be provided - * by various parts of the tcpdump program. + * by various parts of the tcpdump program. Gordon W. Ross * * Boilerplate: * @@ -129,6 +129,7 @@ main(argc, argv) int s; /* Socket file descriptor */ int n, tolen, fromlen, recvcnt; int use_hwa = 0; + int32 vend_magic; int32 xid; progname = strrchr(argv[0], '/'); @@ -142,7 +143,10 @@ main(argc, argv) if (debug) printf("%s: version %s.%d\n", progname, VERSION, PATCHLEVEL); - /* Debugging for compilers with struct padding. */ + /* + * Verify that "struct bootp" has the correct official size. + * (Catch evil compilers that do struct padding.) + */ assert(sizeof(struct bootp) == BP_MINPKTSZ); sndbuf = malloc(BUFLEN); @@ -151,6 +155,10 @@ main(argc, argv) printf("malloc failed\n"); exit(1); } + + /* default magic number */ + bcopy(vm_rfc1048, (char*)&vend_magic, 4); + /* Handle option switches. */ while (argc > 0) { if (argv[0][0] != '-') @@ -168,6 +176,13 @@ main(argc, argv) use_hwa = 1; break; + case 'm': /* Magic number value. */ + if (argc < 2) + goto error; + argc--; argv++; + vend_magic = inet_addr(*argv); + break; + error: default: puts(usage); @@ -309,8 +324,9 @@ main(argc, argv) /* * Copy in the default vendor data. */ - bcopy(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)); - bp->bp_vend[4] = TAG_END; + bcopy((char*)&vend_magic, bp->bp_vend, 4); + if (vend_magic) + bp->bp_vend[4] = TAG_END; /* * Read in the "options" part of the request. @@ -363,7 +379,7 @@ main(argc, argv) } if (n == 0) { /* - * We have not received a response since the last send. + * We have not received a response in the last second. * If we have ever received any responses, exit now. * Otherwise, bump the "wait time" field and re-send. */ diff --git a/usr.sbin/bootp/bootptest/print-bootp.c b/usr.sbin/bootp/bootptest/print-bootp.c index a11f38a63272..1919e7f88660 100644 --- a/usr.sbin/bootp/bootptest/print-bootp.c +++ b/usr.sbin/bootp/bootptest/print-bootp.c @@ -24,8 +24,8 @@ * There is an e-mail list for tcpdump: */ #ifndef lint -/* from: print-bootp.c,v 1.17 91/11/14 22:21:34 leres Exp */ -static char rcsid[] = "$Id: print-bootp.c,v 1.1.1.1 1994/06/27 21:25:50 gwr Exp $"; +static char rcsid[] = "$Id: print-bootp.c,v 1.2 1994/08/22 22:15:01 gwr Exp $"; +/* 93/10/10 New data-driven option print routine. */ #endif #include @@ -39,13 +39,7 @@ static char rcsid[] = "$Id: print-bootp.c,v 1.1.1.1 1994/06/27 21:25:50 gwr Exp #include #include "bootp.h" - -#ifdef BOOTPTEST #include "bootptest.h" -#else /* BOOTPTEST */ -#include "interface.h" -#include "addrtoname.h" -#endif /* BOOTPTEST */ /* These decode the vendor data. */ static void rfc1048_print(); diff --git a/usr.sbin/bootp/common/bootp.h b/usr.sbin/bootp/common/bootp.h index 82ab7da2d750..990bf58838b2 100644 --- a/usr.sbin/bootp/common/bootp.h +++ b/usr.sbin/bootp/common/bootp.h @@ -23,8 +23,8 @@ SOFTWARE. /* * Bootstrap Protocol (BOOTP). RFC951 and RFC1395. * - * from: bootp.h,v 1.3+ 1991/11/01 10:02:29 ww0n Exp ww0n - * $Id: bootp.h,v 1.1.1.1 1994/06/27 21:25:48 gwr Exp $ + * $Id: bootp.h,v 1.2 1994/08/22 22:14:40 gwr Exp $ + * * * This file specifies the "implementation-independent" BOOTP protocol * information which is common to both client and server. @@ -46,7 +46,7 @@ struct bootp { unsigned char bp_hops; /* gateway hops */ unsigned int32 bp_xid; /* transaction ID */ unsigned short bp_secs; /* seconds since boot began */ - unsigned short bp_unused; + unsigned short bp_flags; /* RFC1532 broadcast, etc. */ struct in_addr bp_ciaddr; /* client IP address */ struct in_addr bp_yiaddr; /* 'your' IP address */ struct in_addr bp_siaddr; /* server IP address */ @@ -121,6 +121,9 @@ struct bootp { #define TAG_NIS_DOMAIN ((unsigned char) 40) #define TAG_NIS_SERVER ((unsigned char) 41) #define TAG_NTP_SERVER ((unsigned char) 42) +/* DHCP maximum message size. */ +#define TAG_MAX_MSGSZ ((unsigned char) 57) + /* XXX - Add new tags here */ diff --git a/usr.sbin/bootp/common/bootpd.h b/usr.sbin/bootp/common/bootpd.h index 4c129f434568..e5ce3417c04e 100644 --- a/usr.sbin/bootp/common/bootpd.h +++ b/usr.sbin/bootp/common/bootpd.h @@ -46,6 +46,9 @@ SOFTWARE. #define MAXSTRINGLEN 80 /* Max string length */ +/* Local definitions: */ +#define MAX_MSG_SIZE (3*512) /* Maximum packet size */ + /* * Return pointer to static string which gives full network error message. @@ -121,6 +124,8 @@ struct flag { nis_server :1, ntp_server :1, exec_file :1, + msg_size :1, + min_wait :1, /* XXX - Add new tags here */ vm_cookie :1; }; @@ -176,7 +181,9 @@ struct host { RFC951 only allocates 1 byte. . . */ haddr[MAXHADDRLEN]; int32 time_offset; - unsigned int bootsize; + unsigned int32 bootsize, + msg_size, + min_wait; struct in_addr bootserver, iaddr, swap_server, diff --git a/usr.sbin/bootp/common/dumptab.c b/usr.sbin/bootp/common/dumptab.c index edbaaf0bb063..8c049b99deba 100644 --- a/usr.sbin/bootp/common/dumptab.c +++ b/usr.sbin/bootp/common/dumptab.c @@ -80,6 +80,8 @@ dumptab(filename) #\tip -- host IP address\n\ #\tlg -- log servers\n\ #\tlp -- LPR servers\n\ +#\tms -- message size\n\ +#\tmw -- min wait (secs)\n\ #\tns -- IEN-116 name servers\n\ #\tnt -- NTP servers (RFC 1129)\n\ #\tra -- reply address override\n\ @@ -215,6 +217,12 @@ dump_host(fp, hp) list_ipaddresses(fp, hp->lpr_server); fprintf(fp, ":"); } + if (hp->flags.msg_size) { + fprintf(fp, "\\\n\t:ms=%d:", hp->msg_size); + } + if (hp->flags.min_wait) { + fprintf(fp, "\\\n\t:mw=%d:", hp->min_wait); + } if (hp->flags.name_server) { fprintf(fp, "\\\n\t:ns="); list_ipaddresses(fp, hp->name_server); diff --git a/usr.sbin/bootp/common/hash.c b/usr.sbin/bootp/common/hash.c index ed45d6fbf6c0..c1d33bb85ec6 100644 --- a/usr.sbin/bootp/common/hash.c +++ b/usr.sbin/bootp/common/hash.c @@ -21,7 +21,7 @@ SOFTWARE. ************************************************************************/ #ifndef lint -static char rcsid[] = "$Id: hash.c,v 1.1.1.1 1994/06/27 21:25:48 gwr Exp $"; +static char rcsid[] = "$Id: hash.c,v 1.2 1994/08/22 22:14:58 gwr Exp $"; #endif diff --git a/usr.sbin/bootp/common/patchlevel.h b/usr.sbin/bootp/common/patchlevel.h index 92abc4f116b3..23f45c790244 100644 --- a/usr.sbin/bootp/common/patchlevel.h +++ b/usr.sbin/bootp/common/patchlevel.h @@ -1,3 +1,3 @@ /* patchlevel.h */ -#define VERSION "2.3" -#define PATCHLEVEL 8 +#define VERSION "2.4" +#define PATCHLEVEL 0 diff --git a/usr.sbin/bootp/common/readfile.c b/usr.sbin/bootp/common/readfile.c index 4db317d973b6..1f70b453c07a 100644 --- a/usr.sbin/bootp/common/readfile.c +++ b/usr.sbin/bootp/common/readfile.c @@ -21,7 +21,7 @@ SOFTWARE. ************************************************************************/ #ifndef lint -static char rcsid[] = "$Header: /cvsroot/src/usr.sbin/bootp/common/readfile.c,v 1.1.1.1 1994/06/27 21:25:48 gwr Exp $"; +static char rcsid[] = "$Id: readfile.c,v 1.2 1994/08/22 22:15:04 gwr Exp $"; #endif @@ -80,6 +80,7 @@ static char rcsid[] = "$Header: /cvsroot/src/usr.sbin/bootp/common/readfile.c,v #define E_BAD_LONGWORD (-6) #define E_BAD_HWATYPE (-7) #define E_BAD_PATHNAME (-8) +#define E_BAD_VALUE (-9) /* Tag idendities. */ #define SYM_NULL 0 @@ -115,14 +116,16 @@ static char rcsid[] = "$Header: /cvsroot/src/usr.sbin/bootp/common/readfile.c,v #define SYM_NIS_SERVER 31 /* RFC 1533 */ #define SYM_NTP_SERVER 32 /* RFC 1533 */ #define SYM_EXEC_FILE 33 /* YORK_EX_OPTION */ +#define SYM_MSG_SIZE 34 +#define SYM_MIN_WAIT 35 /* XXX - Add new tags here */ -#define OP_ADDITION 1 /* Operations on tags */ +#define OP_ADDITION 1 /* Operations on tags */ #define OP_DELETION 2 #define OP_BOOLEAN 3 -#define MAXINADDRS 16 /* Max size of an IP address list */ -#define MAXBUFLEN 64 /* Max temp buffer space */ +#define MAXINADDRS 16 /* Max size of an IP address list */ +#define MAXBUFLEN 256 /* Max temp buffer space */ #define MAXENTRYLEN 2048 /* Max size of an entire entry */ @@ -174,6 +177,8 @@ PRIVATE struct symbolmap symbol_list[] = { {"ip", SYM_IPADDR}, {"lg", SYM_LOG_SERVER}, {"lp", SYM_LPR_SERVER}, + {"ms", SYM_MSG_SIZE}, + {"mw", SYM_MIN_WAIT}, {"ns", SYM_NAME_SERVER}, {"nt", SYM_NTP_SERVER}, {"ra", SYM_REPLY_ADDR}, @@ -694,6 +699,8 @@ process_entry(host, src) break; case E_BAD_PATHNAME: msg = "bad pathname (need leading '/')"; + case E_BAD_VALUE: + msg = "bad value"; default: msg = "unkown error"; break; @@ -761,6 +768,19 @@ process_entry(host, src) } \ } while (0) +/* Parse an integer value for MEMBER */ +#define PARSE_INT(MEMBER) do \ +{ \ + if (optype == OP_BOOLEAN) \ + return E_SYNTAX_ERROR; \ + hp->flags.MEMBER = FALSE; \ + if (optype == OP_ADDITION) { \ + value = get_u_long(symbol); \ + hp->MEMBER = value; \ + hp->flags.MEMBER = TRUE; \ + } \ +} while (0) + /* * Evaluate the two-character tag symbol pointed to by "symbol" and place * the data in the structure pointed to by "hp". The pointer pointed to @@ -893,9 +913,6 @@ eval_symbol(symbol, hp) case SYM_HOMEDIR: PARSE_STR(homedir); - if ((hp->homedir != NULL) && - (hp->homedir->string[0] != '/')) - return E_BAD_PATHNAME; break; case SYM_HTYPE: @@ -1103,6 +1120,19 @@ eval_symbol(symbol, hp) break; #endif + case SYM_MSG_SIZE: + PARSE_INT(msg_size); + if (hp->msg_size < BP_MINPKTSZ || + hp->msg_size > MAX_MSG_SIZE) + return E_BAD_VALUE; + break; + + case SYM_MIN_WAIT: + PARSE_INT(min_wait); + if (hp->min_wait < 0) + return E_BAD_VALUE; + break; + /* XXX - Add new tags here */ default: @@ -1480,6 +1510,9 @@ fill_defaults(hp, src) DUP_LINK(exec_file); #endif + DUP_COPY(msg_size); + DUP_COPY(min_wait); + /* XXX - Add new tags here */ DUP_LINK(generic); diff --git a/usr.sbin/bootpd/Announce b/usr.sbin/bootpd/Announce index 0eef65477528..e4ae04c20d84 100644 --- a/usr.sbin/bootpd/Announce +++ b/usr.sbin/bootpd/Announce @@ -4,7 +4,7 @@ from the original BOOTP server created by Bill Croft at Stanford. This version merges most of the enhancements and bug-fixes from the NetBSD, Columbia, and other versions. -New features: +New features in version 2.4 include: Added a simple BOOTP gateway program: bootpgw Allow host name anywhere IP address is expected. @@ -25,8 +25,10 @@ New features: Added RFC 1533 tags 40,41,42 :yd=:ys=:nt=: ConvOldTab.sh to convert old (1.1) bootptab to new format. + Permits extended-length replies with more option data. + +Problems fixed in this version: -Fixes included: Fixed references to free host structures. (used to cause core dump on Solaris) Remove change that added null terminator to string options. @@ -50,9 +52,12 @@ Systems on which I have seen this code work: Systems on which others say this code works: CDC EP/IX (1.4.3, 2.1.1) DEC Ultrix (4.2, 4.3) - NetBSD (Current-1/94) + NetBSD (Current-8/94) OSF/1 (DEC Alpha CPU) +Please direct questions, comments, and bug reports to: + + Gordon W. Ross Mercury Computer Systems gwr@mc.com 199 Riverneck Road 508-256-1300 Chelmsford, MA 01824-2820 diff --git a/usr.sbin/bootpd/Announce.old b/usr.sbin/bootpd/Announce.old new file mode 100644 index 000000000000..c78e3926c987 --- /dev/null +++ b/usr.sbin/bootpd/Announce.old @@ -0,0 +1,141 @@ + +[ Old announcement from version 2.2: ] + +New features in version 2.2 include: + +o A new "td" tag allows the specification of a "TFTP directory" for use + with so-called "secure" implementations of tftpd which chroot(2) to a + particular directory. + +o A new "sa" tag allows the explicit specification of the TFTP + "server address." Formerly, the 'siaddr' field of the BOOTREPLY was + always filled with the IP address of the BOOTP server. The "sa" tag + now allows the BOOTP server and the TFTP server to be two different + machines, if desired. + +o The server now automatically determines whether it is running as a + standalone program (e.g. invoked by hand from a shell) or as a child of + /etc/inetd. The -s option and a new -i option are provided to force + standalone or inetd mode if necessary. + +o When the vendor magic cookie is zero, BOOTP replies now default to the + RFC 1084 vendor format, rather than the old CMU format. This helps + interoperability with uncooperative BOOTP clients which want RFC 1084 + format but don't bother filling in the magic cookie properly to tell + the server... *sigh* (This makes the ":vm=rfc1048:" tag unnecessary + in most cases now. Oh, the "vm" tag now accepts "rfc1084" as well as + "rfc1048" -- they mean the same thing.) + +o Log messages now include the specific network type. For example, rather + than saying "request from hardware address ABCDEF012345", the message is + now "request from Ethernet address ABCEDF012345", or "request from + IEEE802 address 4000A1B2C3D4". + + +Bug fixes in this version include: + +o The automatic bootfile-size calculation now works correctly when the + file size is an exact multiple of 512 octets. It used to return a number + which was one 512-octet unit greater than necessary. + +o A bug in comparing subnet masks has been fixed. + +o A bug in calculating the size of the vendor information area when + inserting the hostname has been fixed. + + +Other changes: + +o The man page has been split into two man pages. One covers the server + itself (bootpd.8) and the other covers the configuration file format + (bootptab.5). + + +[ Old announcement from version 2.1: ] + +Subject: Updated RFC1048 BOOTP server now available + +Well, no surprise, bootpd 2.0 had a few bugs. A new improved version, +bootpd 2.1, is now available for anonymous FTP from lancaster.andrew.cmu.edu +(128.2.13.21). The new server can be found in pub/bootp.2.1.tar. + +Bug fixes and improvements in version 2.1 include: + +o The definition of "access to the bootfile" has been changed to require the + public read access bit to be set. This is required by tftpd(8), so the + server will not reply with a file which a client cannot obtain via TFTP. +o The RFC1084 bootfile size tag has been implemented. It allows either + automatic or manual specification of the bootfile size in 512-octet blocks. +o Generic tags now work as advertised. +o A subtle bug which caused strange parsing behavior under certain conditions + has been fixed. +o The RFC1048 vendor information now has the correct byte order on + little-endien machines such as the VAX. +o Failure to specify the bootfile home directory and/or default bootfile in + the configuration file no longer causes server crashes. The server now + makes a reasonably intelligent choice if this configuration information is + missing. This is documented in the man page. +o BOOTP requests from clients which already know their IP addresses no longer + cause server crashes. + + +Please direct questions, comments, and bug reports to +Walt Wimer or Drew Perkins . +[ Changed: now please send mail to: ] + + +Good luck, + +Walt Wimer +Network Development +Carnegie Mellon University + + +[ Old announcement from version 2.0: ] + +Subject: RFC-1048 compatible BOOTP server now available + + +An RFC-1048 (BOOTP Vendor Information Extensions) compatible BOOTP (RFC-951) +server is now available for anonymous FTP from lancaster.andrew.cmu.edu +(128.2.13.21). The new server can be found in pub/bootp.2.0.tar. This is +an enhanced version of the existing CMU BOOTP server which was derived from +the original BOOTP server created by Bill Croft at Stanford. + +New features and changes in version 2.0 include: + +o Full support for the vendor information extensions described in RFC-1048. +o Faster response time (host lookup via hash table instead of linear search). +o New termcap-like configuration file format which allows greater flexibility + in specifying the variable vendor information of RFC-1048. Host entries + may refer to other hosts as templates so that redundant information need + be specified only once. +o Continued support for the CMU vendor information format. The server may + be configured on a per-host basis to always reply with a certain vendor + information format or to reply based on the client's request. +o Expanded logging. +o The server may now be run by inetd or as a standalone program like the + old version. +o The configuration and debugging dump files may be specified on the command + line. + + +The server has been successfully tested on the following machines: + + IBM RT PC running ACIS 4.3 (4.3 BSD) + Sun 3/50 running SunOS 3.5 + DEC MicroVAX II running Ultrix 1.1 + DEC MicroVAX II running Ultrix 2.2 + + +Please direct questions, comments, and bug reports to +Walt Wimer or Drew Perkins . +[ Changed: now please send mail to: ] + + +Sincerely, + +Walt Wimer +Network Development +Carnegie Mellon University + diff --git a/usr.sbin/bootpd/Changes b/usr.sbin/bootpd/Changes index 222cb8936b84..06165486acc5 100644 --- a/usr.sbin/bootpd/Changes +++ b/usr.sbin/bootpd/Changes @@ -2,6 +2,20 @@ Changes, most recent first Date, Real Name what... +--> bootp-2.4.0 + +08/20/94 gwr@mc.com (Gordon W. Ross) + Fix code to build bootfile name based on combination of + client requested name and bootfile specifications. + Behave similarly with or without CHECK_FILE_ACCESS. + +07/30/94 Dirk Koeppen + Add "min wait" option (mw) to cause bootpd to ignore + requests from clients that have not waited long enough. + Add code to honor client requests containing the DHCP + option "Maximum Message Size" and use its value to + determine the size of the reply message. + --> bootp-2.3.8 06/25/94 Christos Zoulas diff --git a/usr.sbin/bootpd/Makefile.UNIX b/usr.sbin/bootpd/Makefile.UNIX index 3d6bc547dd9e..e333ce5d2ca8 100644 --- a/usr.sbin/bootpd/Makefile.UNIX +++ b/usr.sbin/bootpd/Makefile.UNIX @@ -138,9 +138,6 @@ OBJ_TEST= bootptest.o print-bootp.o getif.o getether.o \ bootptest: $(OBJ_TEST) $(CC) -o $@ $(OBJ_TEST) $(SYSLIBS) -print-bootp.o : print-bootp.c - $(CC) $(CFLAGS) -DBOOTPTEST -c $< - # This is just for testing the lookup functions. TRYLOOK= trylook.o lookup.o report.o $(STRERROR) trylook : $(TRYLOOK) diff --git a/usr.sbin/bootpd/README b/usr.sbin/bootpd/README index 88dd6f8fc486..c7755b786ddb 100644 --- a/usr.sbin/bootpd/README +++ b/usr.sbin/bootpd/README @@ -4,11 +4,9 @@ from the original BOOTP server created by Bill Croft at Stanford. This version merges all the enhancements and bug-fixes from the NetBSD, Columbia, and other versions. -If you have problems or questions about this version, send email to: - gwr@mc.com (Gordon W. Ross) +Please direct questions, comments, and bug reports to the list: + -For general questions about BOOTP, send email to the list: - bootp@andrew.cmu.edu You can subscribe to this mailing list by sending mail to: bootp-request@andrew.cmu.edu (The body of the message should contain: "Add ") @@ -91,9 +89,11 @@ Pittsburgh, PA 15213 [ Contents description by file: ] Announce* Text of release announcements +Changes Change history, reverse chronological Installation Instructions for building and installing Makefile* for "make" README This file +ToDo Things not yet done bootp.h The protocol header file bootpd.8 Manual page for bootpd, boopgw bootpd.c BOOTP server main module diff --git a/usr.sbin/bootpd/bootp.h b/usr.sbin/bootpd/bootp.h index 82ab7da2d750..990bf58838b2 100644 --- a/usr.sbin/bootpd/bootp.h +++ b/usr.sbin/bootpd/bootp.h @@ -23,8 +23,8 @@ SOFTWARE. /* * Bootstrap Protocol (BOOTP). RFC951 and RFC1395. * - * from: bootp.h,v 1.3+ 1991/11/01 10:02:29 ww0n Exp ww0n - * $Id: bootp.h,v 1.1.1.1 1994/06/27 21:25:48 gwr Exp $ + * $Id: bootp.h,v 1.2 1994/08/22 22:14:40 gwr Exp $ + * * * This file specifies the "implementation-independent" BOOTP protocol * information which is common to both client and server. @@ -46,7 +46,7 @@ struct bootp { unsigned char bp_hops; /* gateway hops */ unsigned int32 bp_xid; /* transaction ID */ unsigned short bp_secs; /* seconds since boot began */ - unsigned short bp_unused; + unsigned short bp_flags; /* RFC1532 broadcast, etc. */ struct in_addr bp_ciaddr; /* client IP address */ struct in_addr bp_yiaddr; /* 'your' IP address */ struct in_addr bp_siaddr; /* server IP address */ @@ -121,6 +121,9 @@ struct bootp { #define TAG_NIS_DOMAIN ((unsigned char) 40) #define TAG_NIS_SERVER ((unsigned char) 41) #define TAG_NTP_SERVER ((unsigned char) 42) +/* DHCP maximum message size. */ +#define TAG_MAX_MSGSZ ((unsigned char) 57) + /* XXX - Add new tags here */ diff --git a/usr.sbin/bootpd/bootpd.8 b/usr.sbin/bootpd/bootpd.8 index 481ffd907a13..2956e162d87f 100644 --- a/usr.sbin/bootpd/bootpd.8 +++ b/usr.sbin/bootpd/bootpd.8 @@ -1,6 +1,6 @@ .\" Copyright (c) 1988, 1989, 1991 Carnegie Mellon University .\" -.\" $Header: /cvsroot/src/usr.sbin/bootpd/Attic/bootpd.8,v 1.1.1.1 1994/06/27 21:25:48 gwr Exp $ +.\" $Header: /cvsroot/src/usr.sbin/bootpd/Attic/bootpd.8,v 1.2 1994/08/22 22:14:41 gwr Exp $ .\" .TH BOOTPD 8 "November 06, 1993" "Carnegie Mellon University" .SH NAME diff --git a/usr.sbin/bootpd/bootpd.c b/usr.sbin/bootpd/bootpd.c index 4ca3033c3037..cdd042c3d497 100644 --- a/usr.sbin/bootpd/bootpd.c +++ b/usr.sbin/bootpd/bootpd.c @@ -21,7 +21,7 @@ SOFTWARE. ************************************************************************/ #ifndef lint -static char rcsid[] = "$Id: bootpd.c,v 1.1.1.1 1994/06/27 21:25:49 gwr Exp $"; +static char rcsid[] = "$Id: bootpd.c,v 1.2 1994/08/22 22:14:43 gwr Exp $"; #endif /* @@ -95,9 +95,6 @@ static char rcsid[] = "$Id: bootpd.c,v 1.1.1.1 1994/06/27 21:25:49 gwr Exp $"; #include "tzone.h" #include "patchlevel.h" -/* Local definitions: */ -#define MAXPKT (3*512) /* Maximum packet size */ - #ifndef CONFIG_FILE #define CONFIG_FILE "/etc/bootptab" #endif @@ -220,7 +217,7 @@ main(argc, argv) assert(sizeof(struct bootp) == BP_MINPKTSZ); /* Get space for receiving packets and composing replies. */ - pktbuf = malloc(MAXPKT); + pktbuf = malloc(MAX_MSG_SIZE); if (!pktbuf) { report(LOG_ERR, "malloc failed"); exit(1); @@ -524,7 +521,7 @@ main(argc, argv) exit(0); } ra_len = sizeof(recv_addr); - n = recvfrom(s, pktbuf, MAXPKT, 0, + n = recvfrom(s, pktbuf, MAX_MSG_SIZE, 0, (struct sockaddr *) &recv_addr, &ra_len); if (n <= 0) { continue; @@ -612,11 +609,10 @@ handle_request() int32 bootsize = 0; unsigned hlen, hashcode; int32 dest; -#ifdef CHECK_FILE_ACCESS char realpath[1024]; - char *path; + char *clntpath; + char *homedir, *bootfile; int n; -#endif /* XXX - SLIP init: Set bp_ciaddr = recv_addr here? */ @@ -639,6 +635,7 @@ ignoring request for server %s from client at %s address %s", strcpy(bp->bp_sname, hostname); } + /* Convert the request into a reply. */ bp->bp_op = BOOTREPLY; if (bp->bp_ciaddr.s_addr == 0) { /* @@ -714,6 +711,21 @@ HW addr type is IEEE 802. convert to %s and check again\n", hp->hostname->string); } + /* + * If there is a response delay threshold, ignore requests + * with a timestamp lower than the threshold. + */ + if (hp->flags.min_wait) { + u_int32 t = (u_int32) ntohs(bp->bp_secs); + if (t < hp->min_wait) { + if (debug > 1) + report(LOG_INFO, + "ignoring request due to timestamp (%d < %d)", + t, hp->min_wait); + return; + } + } + #ifdef YORK_EX_OPTION /* * The need for the "ex" tag arose out of the need to empty @@ -785,163 +797,125 @@ HW addr type is IEEE 802. convert to %s and check again\n", */ /* - * XXX - I think the above policy is too complicated. When the - * boot file is missing, it is not obvious why bootpd will not - * respond to client requests. Define CHECK_FILE_ACCESS if you - * want the original complicated policy, otherwise bootpd will - * no longer check for existence of the boot file. -gwr + * XXX - I don't like the policy of ignoring a client when the + * boot file is not accessible. The TFTP server might not be + * running on the same machine as the BOOTP server, in which + * case checking accessibility of the boot file is pointless. + * + * Therefore, file accessibility is now demanded ONLY if you + * define CHECK_FILE_ACCESS in the Makefile options. -gwr */ -#ifdef CHECK_FILE_ACCESS - + /* + * The "real" path is as seen by the BOOTP daemon on this + * machine, while the client path is relative to the TFTP + * daemon chroot directory (i.e. /tftpboot). + */ if (hp->flags.tftpdir) { strcpy(realpath, hp->tftpdir->string); - path = &realpath[strlen(realpath)]; + clntpath = &realpath[strlen(realpath)]; } else { - path = realpath; + clntpath = realpath; } + /* + * Determine client's requested homedir and bootfile. + */ + homedir = NULL; + bootfile = NULL; if (bp->bp_file[0]) { - /* - * The client specified a file. - */ - if (bp->bp_file[0] == '/') { - strcpy(path, bp->bp_file); /* Absolute pathname */ + homedir = bp->bp_file; + bootfile = strrchr(homedir, '/'); + if (bootfile) { + if (homedir == bootfile) + homedir = NULL; + *bootfile++ = '\0'; } else { - if (hp->flags.homedir) { - strcpy(path, hp->homedir->string); - strcat(path, "/"); - strcat(path, bp->bp_file); - } else { - report(LOG_NOTICE, - "requested file \"%s\" not found: hd unspecified", - bp->bp_file); - return; - } + /* no "/" in the string */ + bootfile = homedir; + homedir = NULL; } - } else { - /* - * No file specified by the client. - */ - if (hp->flags.bootfile && ((hp->bootfile->string)[0] == '/')) { - strcpy(path, hp->bootfile->string); - } else if (hp->flags.homedir && hp->flags.bootfile) { - strcpy(path, hp->homedir->string); - strcat(path, "/"); - strcat(path, hp->bootfile->string); - } else { - bzero(bp->bp_file, sizeof(bp->bp_file)); - goto skip_file; /* Don't bother trying to access the file */ + if (debug > 2) { + report(LOG_INFO, "requested path=\"%s\" file=\"%s\"", + (homedir) ? homedir : "", + (bootfile) ? bootfile : ""); } } + /* + * Specifications in bootptab override client requested values. + */ + if (hp->flags.homedir) + homedir = hp->homedir->string; + if (hp->flags.bootfile) + bootfile = hp->bootfile->string; + + /* + * Construct bootfile path. + */ + if (homedir) { + if (homedir[0] != '/') + strcat(clntpath, "/"); + strcat(clntpath, homedir); + homedir = NULL; + } + if (bootfile) { + if (bootfile[0] != '/') + strcat(clntpath, "/"); + strcat(clntpath, bootfile); + bootfile = NULL; + } + /* * First try to find the file with a ".host" suffix */ - n = strlen(path); - strcat(path, "."); - strcat(path, hp->hostname->string); + n = strlen(clntpath); + strcat(clntpath, "."); + strcat(clntpath, hp->hostname->string); if (chk_access(realpath, &bootsize) < 0) { - path[n] = 0; /* Try it without the suffix */ + clntpath[n] = 0; /* Try it without the suffix */ if (chk_access(realpath, &bootsize) < 0) { + /* neither "file.host" nor "file" was found */ +#ifdef CHECK_FILE_ACCESS + if (bp->bp_file[0]) { /* * Client wanted specific file * and we didn't have it. */ report(LOG_NOTICE, - "requested file not found: \"%s\"", path); + "requested file not found: \"%s\"", clntpath); return; - } else { - /* - * Client didn't ask for a specific file and we couldn't - * access the default file, so just zero-out the bootfile - * field in the packet and continue processing the reply. - */ - bzero(bp->bp_file, sizeof(bp->bp_file)); - goto skip_file; } - } - } - strcpy(bp->bp_file, path); + /* + * Client didn't ask for a specific file and we couldn't + * access the default file, so just zero-out the bootfile + * field in the packet and continue processing the reply. + */ + bzero(bp->bp_file, sizeof(bp->bp_file)); + goto null_file_name; - skip_file: - ; - #else /* CHECK_FILE_ACCESS */ - /* - * This implements a simple response policy, where bootpd - * will fail to respond only if it knows nothing about - * the client that sent the request. This plugs in the - * boot file name but does not demand that it exist. - * - * If either the client or the server specifies a boot file, - * build the path name for it. Server boot file preferred. - */ - if (bp->bp_file[0] || hp->flags.bootfile) { - char requested_file[BP_FILE_LEN]; - char *given_file; - char *p = bp->bp_file; - int space = BP_FILE_LEN; - int n; + /* Complain only if boot file size was needed. */ + if (hp->flags.bootsize_auto) { + report(LOG_ERR, "can not determine size of file \"%s\"", + clntpath); + } - /* Save client's requested file name. */ - strncpy(requested_file, bp->bp_file, BP_FILE_LEN); - - /* If tftpdir is set, insert it. */ - if (hp->flags.tftpdir) { - n = strlen(hp->tftpdir->string); - if ((n+1) >= space) - goto nospc; - strcpy(p, hp->tftpdir->string); - p += n; - space -= n; - } - - /* If homedir is set, insert it. */ - if (hp->flags.homedir) { - n = strlen(hp->homedir->string); - if ((n+1) >= space) - goto nospc; - strcpy(p, hp->homedir->string); - p += n; - space -= n; - } - - /* Finally, append the boot file name. */ - if (hp->flags.bootfile) - given_file = hp->bootfile->string; - else - given_file = requested_file; - assert(given_file); - n = strlen(given_file); - if ((n+1) >= space) - goto nospc; - strcpy(p, given_file); - p += n; - space -= n; - *p = '\0'; - - if (space <= 0) { - nospc: - report(LOG_ERR, "boot file path too long (%s)", - hp->hostname->string); +#endif /* CHECK_FILE_ACCESS */ } } + strncpy(bp->bp_file, clntpath, BP_FILE_LEN); + if (debug > 2) + report(LOG_INFO, "bootfile=\"%s\"", clntpath); - /* Determine boot file size if requested. */ - if (hp->flags.bootsize_auto) { - if (bp->bp_file[0] == '\0' || - chk_access(bp->bp_file, &bootsize) < 0) - { - report(LOG_ERR, "can not determine boot file size for %s", - hp->hostname->string); - } - } +null_file_name: -#endif /* CHECK_FILE_ACCESS */ + /* + * Handle vendor options based on magic number. + */ if (debug > 1) { report(LOG_INFO, "vendor magic field is %d.%d.%d.%d", @@ -1018,12 +992,15 @@ sendreply(forward, dst_override) struct bootp *bp = (struct bootp *) pktbuf; struct in_addr dst; u_short port = bootpc_port; -#if 0 - u_char canon_haddr[MAXHADDRLEN]; -#endif unsigned char *ha; int len; + /* + * XXX - Should honor bp_flags "broadcast" bit here. + * Temporary workaround: use the :ra=ADDR: option to + * set the reply address to the broadcast address. + */ + /* * If the destination address was specified explicitly * (i.e. the broadcast address for HP compatiblity) @@ -1055,17 +1032,7 @@ sendreply(forward, dst_override) len = bp->bp_hlen; if (len > MAXHADDRLEN) len = MAXHADDRLEN; -#if 0 - /* - * XXX - Is this necessary, given that the HW address - * in bp_chaddr was left as the client provided it? - * Does some DEC version of TCP/IP need this? -gwr - */ - if (bp->bp_htype == HTYPE_IEEE802) { - haddr_conv802(ha, canon_haddr, len); - ha = canon_haddr; - } -#endif + if (debug > 1) report(LOG_INFO, "setarp %s - %s", inet_ntoa(dst), haddrtoa(ha, len)); @@ -1243,8 +1210,77 @@ dovend_rfc1048(bp, hp, bootsize) static char noroom[] = "%s: No room for \"%s\" option"; vp = bp->bp_vend; - bytesleft = sizeof(bp->bp_vend); /* Initial vendor area size */ - bcopy(vm_rfc1048, vp, 4); /* Copy in the magic cookie */ + + if (hp->flags.msg_size) { + pktlen = hp->msg_size; + } else { + /* + * If the request was longer than the official length, build + * a response of that same length where the additional length + * is assumed to be part of the bp_vend (options) area. + */ + if (pktlen > sizeof(*bp)) { + if (debug > 1) + report(LOG_INFO, "request message length=%d", pktlen); + } + /* + * Check whether the request contains the option: + * Maximum DHCP Message Size (RFC1533 sec. 9.8) + * and if so, override the response length with its value. + * This request must lie within the first BP_VEND_LEN + * bytes of the option space. + */ + { + byte *p, *ep; + byte tag, len; + short msgsz = 0; + + p = vp + 4; + ep = p + BP_VEND_LEN - 4; + while (p < ep) { + tag = *p++; + /* Check for tags with no data first. */ + if (tag == TAG_PAD) + continue; + if (tag == TAG_END) + break; + /* Now scan the length byte. */ + len = *p++; + switch (tag) { + case TAG_MAX_MSGSZ: + if (len == 2) { + bcopy(p, (char*)&msgsz, 2); + msgsz = ntohs(msgsz); + } + break; + case TAG_SUBNET_MASK: + /* XXX - Should preserve this if given... */ + break; + } /* swtich */ + p += len; + } + + if (msgsz > sizeof(*bp)) { + if (debug > 1) + report(LOG_INFO, "request has DHCP msglen=%d", msgsz); + pktlen = msgsz; + } + } + } + + if (pktlen < sizeof(*bp)) { + report(LOG_ERR, "invalid response length=%d", pktlen); + pktlen = sizeof(*bp); + } + bytesleft = ((byte*)bp + pktlen) - vp; + if (pktlen > sizeof(*bp)) { + if (debug > 1) + report(LOG_INFO, "extended reply, length=%d, options=%d", + pktlen, bytesleft); + } + + /* Copy in the magic cookie */ + bcopy(vm_rfc1048, vp, 4); vp += 4; bytesleft -= 4; diff --git a/usr.sbin/bootpd/bootpd.h b/usr.sbin/bootpd/bootpd.h index 4c129f434568..e5ce3417c04e 100644 --- a/usr.sbin/bootpd/bootpd.h +++ b/usr.sbin/bootpd/bootpd.h @@ -46,6 +46,9 @@ SOFTWARE. #define MAXSTRINGLEN 80 /* Max string length */ +/* Local definitions: */ +#define MAX_MSG_SIZE (3*512) /* Maximum packet size */ + /* * Return pointer to static string which gives full network error message. @@ -121,6 +124,8 @@ struct flag { nis_server :1, ntp_server :1, exec_file :1, + msg_size :1, + min_wait :1, /* XXX - Add new tags here */ vm_cookie :1; }; @@ -176,7 +181,9 @@ struct host { RFC951 only allocates 1 byte. . . */ haddr[MAXHADDRLEN]; int32 time_offset; - unsigned int bootsize; + unsigned int32 bootsize, + msg_size, + min_wait; struct in_addr bootserver, iaddr, swap_server, diff --git a/usr.sbin/bootpd/bootpef.c b/usr.sbin/bootpd/bootpef.c index e3f17f18f6ba..4b2e3f405cde 100644 --- a/usr.sbin/bootpd/bootpef.c +++ b/usr.sbin/bootpd/bootpef.c @@ -21,7 +21,7 @@ SOFTWARE. ************************************************************************/ #ifndef lint -static char rcsid[] = "$Id: bootpef.c,v 1.1.1.1 1994/06/27 21:25:49 gwr Exp $"; +static char rcsid[] = "$Id: bootpef.c,v 1.2 1994/08/22 22:14:46 gwr Exp $"; #endif diff --git a/usr.sbin/bootpd/bootpgw.c b/usr.sbin/bootpd/bootpgw.c index 937a10b47d50..f157ccac9e85 100644 --- a/usr.sbin/bootpd/bootpgw.c +++ b/usr.sbin/bootpd/bootpgw.c @@ -26,7 +26,7 @@ SOFTWARE. ************************************************************************/ #ifndef lint -static char rcsid[] = "$Id: bootpgw.c,v 1.1.1.1 1994/06/27 21:25:51 gwr Exp $"; +static char rcsid[] = "$Id: bootpgw.c,v 1.2 1994/08/22 22:14:48 gwr Exp $"; #endif /* @@ -78,7 +78,7 @@ static char rcsid[] = "$Id: bootpgw.c,v 1.1.1.1 1994/06/27 21:25:51 gwr Exp $"; #include "patchlevel.h" /* Local definitions: */ -#define MAXPKT (3*512) /* Maximum packet size */ +#define MAX_MSG_SIZE (3*512) /* Maximum packet size */ #define TRUE 1 #define FALSE 0 #define get_network_errmsg get_errmsg @@ -184,7 +184,7 @@ main(argc, argv) assert(sizeof(struct bootp) == BP_MINPKTSZ); /* Get space for receiving packets and composing replies. */ - pktbuf = malloc(MAXPKT); + pktbuf = malloc(MAX_MSG_SIZE); if (!pktbuf) { report(LOG_ERR, "malloc failed"); exit(1); @@ -455,7 +455,7 @@ main(argc, argv) exit(0); } ra_len = sizeof(recv_addr); - n = recvfrom(s, pktbuf, MAXPKT, 0, + n = recvfrom(s, pktbuf, MAX_MSG_SIZE, 0, (struct sockaddr *) &recv_addr, &ra_len); if (n <= 0) { continue; diff --git a/usr.sbin/bootpd/bootptab.5 b/usr.sbin/bootpd/bootptab.5 index 6ffed2038184..0d1861e67df6 100644 --- a/usr.sbin/bootpd/bootptab.5 +++ b/usr.sbin/bootpd/bootptab.5 @@ -1,6 +1,6 @@ .\" Copyright (c) 1988, 1989, 1991 Carnegie Mellon University .\" -.\" $Header: /cvsroot/src/usr.sbin/bootpd/Attic/bootptab.5,v 1.1.1.1 1994/06/27 21:25:48 gwr Exp $ +.\" $Header: /cvsroot/src/usr.sbin/bootpd/Attic/bootptab.5,v 1.2 1994/08/22 22:14:51 gwr Exp $ .\" .TH BOOTPTAB 5 "October 31, 1991" "Carnegie Mellon University" .UC 6 diff --git a/usr.sbin/bootpd/bootptab.mcs b/usr.sbin/bootpd/bootptab.mcs index ea8296f8fd6d..6fa04d1347eb 100644 --- a/usr.sbin/bootpd/bootptab.mcs +++ b/usr.sbin/bootpd/bootptab.mcs @@ -41,9 +41,9 @@ # First, we define a global entry which specifies the stuff every host uses. -# If you leave "td" and "hd" unset, run bootpd with the "-c /tftpboot" -# switch so path names (boot files) will be interpreted relative to -# the same directory as tftpd will use as its CWD. +# If you leave "td" empty, run bootpd with the "-c /tftpboot" switch +# so path names (boot files) will be interpreted relative to the same +# directory as tftpd will use when opening files. .default:\ :hn:dn="mc.com":\ :td=/tftpboot:\ @@ -82,14 +82,11 @@ eps1: tc=.subnet16:ha=00.80.A3.04.1D.78: tp885: tc=.subnet17:ha=08.00.4C.00.2F.74:bf=tp885sys2.cfe: # MVME147 VxWorks board. -mvme147:tc=.subnet17:ha=08.00.3e.20.da.47:bf=mv147vxw.st: +#mvme147:tc=.subnet17:ha=08.00.3e.20.da.47:bf=mv147vxw.st: # These are just for testing -walnut:tc=.subnet16:ha=walnut:sa=merlin-gw:\ - :td@:hd=/export/walnut/: - -banana:tc=.subnet17:ha=banana:bf=boot.sun4c: -thor:tc=.subnet17:ha=thor:bf=boot.sun4e: - -classic: tc=.subnet16:ha=08.00.20.04.95.3E: +walnut:tc=.subnet16:ha=walnut: +banana:tc=.subnet17:ha=banana: +thor:tc=.subnet17:ha=thor: +classic:tc=.subnet16:ha=classic: diff --git a/usr.sbin/bootpd/bootptest.8 b/usr.sbin/bootpd/bootptest.8 index a564bcf0a337..d076c8bc25b6 100644 --- a/usr.sbin/bootpd/bootptest.8 +++ b/usr.sbin/bootpd/bootptest.8 @@ -6,8 +6,16 @@ bootptest \- send BOOTP queries and print responses .LP .B bootptest [ +.B \-f +.I bootfile +] +[ .B \-h ] +[ +.B \-m +.I magic_number +] .I server\-name .RI [ template-file ] .SH DESCRIPTION @@ -21,10 +29,20 @@ After a response is received, will wait one more second listening for additional responses. .SH OPTIONS .TP +.B \-f +.I bootfile +Fill in the boot file field of the request with +.IR bootfile . +.TP .B \-h Use the hardware (Ethernet) address to identify the client. By default, the IP address is copied into the request indicating that this client already knows its IP address. +.TP +.B \-m +.I magic_number +Initialize the first word of the vendor options field with +.IR magic_number . .LP A .I template-file diff --git a/usr.sbin/bootpd/bootptest.c b/usr.sbin/bootpd/bootptest.c index b288641232ef..bc235ac10650 100644 --- a/usr.sbin/bootpd/bootptest.c +++ b/usr.sbin/bootpd/bootptest.c @@ -5,9 +5,9 @@ * various places, including the CMU BOOTP client and server. * The packet printing routine is from the Berkeley "tcpdump" * program with some enhancements I added. The print-bootp.c - * file is shared with my copy of "tcpdump" and therefore uses + * file was shared with my copy of "tcpdump" and therefore uses * some unusual utility routines that would normally be provided - * by various parts of the tcpdump program. + * by various parts of the tcpdump program. Gordon W. Ross * * Boilerplate: * @@ -129,6 +129,7 @@ main(argc, argv) int s; /* Socket file descriptor */ int n, tolen, fromlen, recvcnt; int use_hwa = 0; + int32 vend_magic; int32 xid; progname = strrchr(argv[0], '/'); @@ -142,7 +143,10 @@ main(argc, argv) if (debug) printf("%s: version %s.%d\n", progname, VERSION, PATCHLEVEL); - /* Debugging for compilers with struct padding. */ + /* + * Verify that "struct bootp" has the correct official size. + * (Catch evil compilers that do struct padding.) + */ assert(sizeof(struct bootp) == BP_MINPKTSZ); sndbuf = malloc(BUFLEN); @@ -151,6 +155,10 @@ main(argc, argv) printf("malloc failed\n"); exit(1); } + + /* default magic number */ + bcopy(vm_rfc1048, (char*)&vend_magic, 4); + /* Handle option switches. */ while (argc > 0) { if (argv[0][0] != '-') @@ -168,6 +176,13 @@ main(argc, argv) use_hwa = 1; break; + case 'm': /* Magic number value. */ + if (argc < 2) + goto error; + argc--; argv++; + vend_magic = inet_addr(*argv); + break; + error: default: puts(usage); @@ -309,8 +324,9 @@ main(argc, argv) /* * Copy in the default vendor data. */ - bcopy(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)); - bp->bp_vend[4] = TAG_END; + bcopy((char*)&vend_magic, bp->bp_vend, 4); + if (vend_magic) + bp->bp_vend[4] = TAG_END; /* * Read in the "options" part of the request. @@ -363,7 +379,7 @@ main(argc, argv) } if (n == 0) { /* - * We have not received a response since the last send. + * We have not received a response in the last second. * If we have ever received any responses, exit now. * Otherwise, bump the "wait time" field and re-send. */ diff --git a/usr.sbin/bootpd/dumptab.c b/usr.sbin/bootpd/dumptab.c index edbaaf0bb063..8c049b99deba 100644 --- a/usr.sbin/bootpd/dumptab.c +++ b/usr.sbin/bootpd/dumptab.c @@ -80,6 +80,8 @@ dumptab(filename) #\tip -- host IP address\n\ #\tlg -- log servers\n\ #\tlp -- LPR servers\n\ +#\tms -- message size\n\ +#\tmw -- min wait (secs)\n\ #\tns -- IEN-116 name servers\n\ #\tnt -- NTP servers (RFC 1129)\n\ #\tra -- reply address override\n\ @@ -215,6 +217,12 @@ dump_host(fp, hp) list_ipaddresses(fp, hp->lpr_server); fprintf(fp, ":"); } + if (hp->flags.msg_size) { + fprintf(fp, "\\\n\t:ms=%d:", hp->msg_size); + } + if (hp->flags.min_wait) { + fprintf(fp, "\\\n\t:mw=%d:", hp->min_wait); + } if (hp->flags.name_server) { fprintf(fp, "\\\n\t:ns="); list_ipaddresses(fp, hp->name_server); diff --git a/usr.sbin/bootpd/hash.c b/usr.sbin/bootpd/hash.c index ed45d6fbf6c0..c1d33bb85ec6 100644 --- a/usr.sbin/bootpd/hash.c +++ b/usr.sbin/bootpd/hash.c @@ -21,7 +21,7 @@ SOFTWARE. ************************************************************************/ #ifndef lint -static char rcsid[] = "$Id: hash.c,v 1.1.1.1 1994/06/27 21:25:48 gwr Exp $"; +static char rcsid[] = "$Id: hash.c,v 1.2 1994/08/22 22:14:58 gwr Exp $"; #endif diff --git a/usr.sbin/bootpd/patchlevel.h b/usr.sbin/bootpd/patchlevel.h index 92abc4f116b3..23f45c790244 100644 --- a/usr.sbin/bootpd/patchlevel.h +++ b/usr.sbin/bootpd/patchlevel.h @@ -1,3 +1,3 @@ /* patchlevel.h */ -#define VERSION "2.3" -#define PATCHLEVEL 8 +#define VERSION "2.4" +#define PATCHLEVEL 0 diff --git a/usr.sbin/bootpd/print-bootp.c b/usr.sbin/bootpd/print-bootp.c index a11f38a63272..1919e7f88660 100644 --- a/usr.sbin/bootpd/print-bootp.c +++ b/usr.sbin/bootpd/print-bootp.c @@ -24,8 +24,8 @@ * There is an e-mail list for tcpdump: */ #ifndef lint -/* from: print-bootp.c,v 1.17 91/11/14 22:21:34 leres Exp */ -static char rcsid[] = "$Id: print-bootp.c,v 1.1.1.1 1994/06/27 21:25:50 gwr Exp $"; +static char rcsid[] = "$Id: print-bootp.c,v 1.2 1994/08/22 22:15:01 gwr Exp $"; +/* 93/10/10 New data-driven option print routine. */ #endif #include @@ -39,13 +39,7 @@ static char rcsid[] = "$Id: print-bootp.c,v 1.1.1.1 1994/06/27 21:25:50 gwr Exp #include #include "bootp.h" - -#ifdef BOOTPTEST #include "bootptest.h" -#else /* BOOTPTEST */ -#include "interface.h" -#include "addrtoname.h" -#endif /* BOOTPTEST */ /* These decode the vendor data. */ static void rfc1048_print(); diff --git a/usr.sbin/bootpd/readfile.c b/usr.sbin/bootpd/readfile.c index 09a6558a5b47..1f70b453c07a 100644 --- a/usr.sbin/bootpd/readfile.c +++ b/usr.sbin/bootpd/readfile.c @@ -21,7 +21,7 @@ SOFTWARE. ************************************************************************/ #ifndef lint -static char rcsid[] = "$Header: /cvsroot/src/usr.sbin/bootpd/Attic/readfile.c,v 1.1.1.1 1994/06/27 21:25:48 gwr Exp $"; +static char rcsid[] = "$Id: readfile.c,v 1.2 1994/08/22 22:15:04 gwr Exp $"; #endif @@ -80,6 +80,7 @@ static char rcsid[] = "$Header: /cvsroot/src/usr.sbin/bootpd/Attic/readfile.c,v #define E_BAD_LONGWORD (-6) #define E_BAD_HWATYPE (-7) #define E_BAD_PATHNAME (-8) +#define E_BAD_VALUE (-9) /* Tag idendities. */ #define SYM_NULL 0 @@ -115,14 +116,16 @@ static char rcsid[] = "$Header: /cvsroot/src/usr.sbin/bootpd/Attic/readfile.c,v #define SYM_NIS_SERVER 31 /* RFC 1533 */ #define SYM_NTP_SERVER 32 /* RFC 1533 */ #define SYM_EXEC_FILE 33 /* YORK_EX_OPTION */ +#define SYM_MSG_SIZE 34 +#define SYM_MIN_WAIT 35 /* XXX - Add new tags here */ -#define OP_ADDITION 1 /* Operations on tags */ +#define OP_ADDITION 1 /* Operations on tags */ #define OP_DELETION 2 #define OP_BOOLEAN 3 -#define MAXINADDRS 16 /* Max size of an IP address list */ -#define MAXBUFLEN 64 /* Max temp buffer space */ +#define MAXINADDRS 16 /* Max size of an IP address list */ +#define MAXBUFLEN 256 /* Max temp buffer space */ #define MAXENTRYLEN 2048 /* Max size of an entire entry */ @@ -174,6 +177,8 @@ PRIVATE struct symbolmap symbol_list[] = { {"ip", SYM_IPADDR}, {"lg", SYM_LOG_SERVER}, {"lp", SYM_LPR_SERVER}, + {"ms", SYM_MSG_SIZE}, + {"mw", SYM_MIN_WAIT}, {"ns", SYM_NAME_SERVER}, {"nt", SYM_NTP_SERVER}, {"ra", SYM_REPLY_ADDR}, @@ -694,6 +699,8 @@ process_entry(host, src) break; case E_BAD_PATHNAME: msg = "bad pathname (need leading '/')"; + case E_BAD_VALUE: + msg = "bad value"; default: msg = "unkown error"; break; @@ -761,6 +768,19 @@ process_entry(host, src) } \ } while (0) +/* Parse an integer value for MEMBER */ +#define PARSE_INT(MEMBER) do \ +{ \ + if (optype == OP_BOOLEAN) \ + return E_SYNTAX_ERROR; \ + hp->flags.MEMBER = FALSE; \ + if (optype == OP_ADDITION) { \ + value = get_u_long(symbol); \ + hp->MEMBER = value; \ + hp->flags.MEMBER = TRUE; \ + } \ +} while (0) + /* * Evaluate the two-character tag symbol pointed to by "symbol" and place * the data in the structure pointed to by "hp". The pointer pointed to @@ -893,9 +913,6 @@ eval_symbol(symbol, hp) case SYM_HOMEDIR: PARSE_STR(homedir); - if ((hp->homedir != NULL) && - (hp->homedir->string[0] != '/')) - return E_BAD_PATHNAME; break; case SYM_HTYPE: @@ -1103,6 +1120,19 @@ eval_symbol(symbol, hp) break; #endif + case SYM_MSG_SIZE: + PARSE_INT(msg_size); + if (hp->msg_size < BP_MINPKTSZ || + hp->msg_size > MAX_MSG_SIZE) + return E_BAD_VALUE; + break; + + case SYM_MIN_WAIT: + PARSE_INT(min_wait); + if (hp->min_wait < 0) + return E_BAD_VALUE; + break; + /* XXX - Add new tags here */ default: @@ -1480,6 +1510,9 @@ fill_defaults(hp, src) DUP_LINK(exec_file); #endif + DUP_COPY(msg_size); + DUP_COPY(min_wait); + /* XXX - Add new tags here */ DUP_LINK(generic);