Rearrange bootpd
This commit is contained in:
commit
68e1cd350c
63
libexec/bootpd/Announce
Normal file
63
libexec/bootpd/Announce
Normal file
@ -0,0 +1,63 @@
|
||||
|
||||
This is an enhanced version of the CMU BOOTP server which was derived
|
||||
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 in version 2.4 include:
|
||||
|
||||
Added a simple BOOTP gateway program: bootpgw
|
||||
Allow host name anywhere IP address is expected.
|
||||
Automatically lookup the IP address when the name of a
|
||||
bootptab entry is a valid hostname.
|
||||
(Dummy entries names should start with '.')
|
||||
Merged changes from NetBSD and Columbia versions.
|
||||
Merged changes for Solaris-2.X and SVR4 systems.
|
||||
Combined bootptest into the bootp release.
|
||||
Merged tag 18 support (:ef=...:) from Jason Zions.
|
||||
Use :ef=extension_file_name: and make the
|
||||
extension files for all clients using bootpef.
|
||||
Merged HP compatibility (:ra=...:) from David R Linn.
|
||||
Allows you to override the reply address.
|
||||
(i.e. send the reply to a broadcast address)
|
||||
Add /etc/ethers support for NetBSD.
|
||||
More systems support getether (Ultrix, OSF, NetBSD)
|
||||
Added RFC 1533 tags 40,41,42
|
||||
:yd=<NIS domain>:ys=<NIS server>:nt=<NTP server>:
|
||||
ConvOldTab.sh to convert old (1.1) bootptab to new format.
|
||||
Permits extended-length replies with more option data.
|
||||
|
||||
Problems fixed in this version:
|
||||
|
||||
Fixed references to free host structures.
|
||||
(used to cause core dump on Solaris)
|
||||
Remove change that added null terminator to string options.
|
||||
(this annoyed some clients...)
|
||||
Add missing symbols to dump routine, fix order.
|
||||
Works (again) with no -DSYSLOGD defined.
|
||||
Fixed several more NULL references in readfile.
|
||||
Added proper length checks to option insertions.
|
||||
Fixed bootptest IP address printing.
|
||||
Cleaned-up signed/unsigned and byteorder bugs.
|
||||
Added SVR4/Streams support to getif and getether
|
||||
Removed extra newlines in syslog messages.
|
||||
Specify facility code when calling syslog(3)
|
||||
When lookup_hwa fails, assume numeric HW address.
|
||||
|
||||
Systems on which I have seen this code work:
|
||||
SunOS 4.X (Solaris 1.X)
|
||||
SunOS 5.X (Solaris 2.X)
|
||||
System V/386 Rel. 4.0
|
||||
|
||||
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-8/94)
|
||||
OSF/1 (DEC Alpha CPU)
|
||||
|
||||
Please direct questions, comments, and bug reports to:
|
||||
<bootp@andrew.cmu.edu>
|
||||
|
||||
Gordon W. Ross Mercury Computer Systems
|
||||
gwr@mc.com 199 Riverneck Road
|
||||
508-256-1300 Chelmsford, MA 01824-2820
|
245
libexec/bootpd/Changes
Normal file
245
libexec/bootpd/Changes
Normal file
@ -0,0 +1,245 @@
|
||||
Changes, most recent first
|
||||
Date, <email> 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 <dirk@incom.de>
|
||||
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 <christos@deshaw.com>
|
||||
Add "-h" flag to override host name (affects default IP
|
||||
address provided in reply messages. (Also minor bug fix)
|
||||
|
||||
05/27/94 gwr@mc.com (Gordon W. Ross)
|
||||
Add code to call "arp -s IPADDR HWADDR" on systems
|
||||
that do not provide an SIOCSARP ioctl (i.e. NetBSD)
|
||||
|
||||
--> bootp-2.3.7
|
||||
|
||||
05/05/94 Walter Wong <wcw+@CMU.EDU>
|
||||
Reduce noize at debug level one, where log messages
|
||||
are generated only for hosts that are recognized
|
||||
and replied to by bootpd. (At request of HP folks.)
|
||||
|
||||
04/30/94 gwr@mc.com (Gordon W. Ross)
|
||||
Use memxxx functions unless USE_BFUNCS is defined.
|
||||
Added -f <file> option to bootptest (requested file).
|
||||
|
||||
04/29/94 tpaquett@ita.lgc.com (Trevor Paquette)
|
||||
Remove call to haddr_conv802() in sendreply().
|
||||
The setarp should get the non-transformed address.
|
||||
|
||||
04/27/94 gwr@mc.com
|
||||
Improve logic for building bootfile pathname, so a path
|
||||
will be put in the reply if either the client or bootpd
|
||||
specifies a boot file. (Needed for NetBSD diskless boot)
|
||||
|
||||
04/25/94 shamash@boxhill.com (Ari Shamash)
|
||||
Fix prs_inetaddr() so it allows '_' in hostnames.
|
||||
|
||||
04/16/94 gwr@mc.com (Gordon W. Ross)
|
||||
Fix setarp for SVR4 (needs to use I_STR ioctl)
|
||||
Thanks to several people: (all sent the same fix)
|
||||
Barney Wolff <barney@databus.com>,
|
||||
bear@upsys.se (Bj|rn Sj|holm),
|
||||
Michael Kuschke <Michael.Kuschke@Materna.DE>,
|
||||
|
||||
03/25/95 Ulrich Heuer </I=zhhi9/G=Ulrich/S=Heuer/@zhflur.ubs.ubs.ch>
|
||||
Make option string lengths not include a null terminator.
|
||||
The trailing null breaks some clients.
|
||||
|
||||
03/15/94 "Edmund J. Sutcliffe" <ejs1@tower.york.ac.uk>
|
||||
Add support for the "EX" option: Execute a program
|
||||
before sending a BOOTREPLY to a client. Support for
|
||||
this option is conditional on YORK_EX_OPTION.
|
||||
|
||||
03/10/94 Nigel Metheringham <nigelm@ohm.york.ac.uk>
|
||||
Make getether.c work on Linux.
|
||||
|
||||
03/09/94 Koch@Math.Uni-Duisburg.DE (Peter Koch)
|
||||
Add missing MANDIR definition to Makefile.
|
||||
|
||||
03/08/94 Jeroen.Scheerder@let.ruu.nl
|
||||
Fix args to report in getether code for Ultrix.
|
||||
Run install individually for each program.
|
||||
|
||||
--> bootp-2.3.6
|
||||
03/07/94 gwr@mc.com
|
||||
Cleanup for release (run gnu indent, tab-size=4)
|
||||
|
||||
02/24/94 Jeroen.Scheerder@let.ruu.nl
|
||||
Allow underscore in host names - readfile.c:goodname()
|
||||
Add ConvOldTab.sh - converts 1.1 bootptab to new format.
|
||||
|
||||
02/20/94 gwr@mc.com (Gordon W. Ross)
|
||||
Make readfile tolerant of hardware addresses that start
|
||||
with a letter. (If lookup_hwa() fails, assume numeric.)
|
||||
Fix whitespace skip before :vm= auto: and avoid lookup.
|
||||
|
||||
02/12/94 walker@zk3.dec.com (Mary Walker)
|
||||
Added support for 64-bit longs (for the DEC Alpha)
|
||||
Allow ieee802 hardware address in bit-reversed oreder
|
||||
|
||||
02/07/94 hl@tekla.fi (Harald Lundberg)
|
||||
Fix conflict with DUMP_FILE in syslog.h on OSF1
|
||||
Use int for (struct bootp).bp_xid (for DEC Alpha)
|
||||
Added Ultrix support to bootptest (getether)
|
||||
|
||||
02/06/94 brezak@ch.hp.com (John Brezak)
|
||||
Add man-page and install targets to Makefile.NetBSD
|
||||
Add getether support for NetBSD
|
||||
|
||||
02/05/94 gwr@mc.com (Gordon W. Ross)
|
||||
Added tags 40,41,42 (NIS domain, NIS server, NTP server)
|
||||
Add stub to getether for machines not yet supported.
|
||||
|
||||
--> bootp-2.3.5
|
||||
01/29/94 gwr@mc.com (Gordon W. Ross)
|
||||
Make bootpgw put a correct address in "giaddr" when
|
||||
the client request came via broadcast.
|
||||
|
||||
01/22/94 gwr@mc.com (Gordon W. Ross)
|
||||
Fix syslog call (missing "facility" code)
|
||||
Add SVR4/Streams support to getif() and getether()
|
||||
Fix getif bug (matched when it should not)
|
||||
Macro-ize lots of similar cases in readfile.c
|
||||
|
||||
12/27/93 brezak@ch.hp.com (John Brezak)
|
||||
Remove all newlines passed to syslog(3)
|
||||
Add /etc/ethers support for NetBSD.
|
||||
|
||||
12/18/93 gwr@mc.com (Gordon W. Ross)
|
||||
Fix bootptest IP address printing.
|
||||
Fix byte-order bugs in bootpgw and bootptest.
|
||||
Clean-up signed/unsigned mismatches.
|
||||
Back out SLIP support changes for now
|
||||
(code fragment saved in ToDo).
|
||||
|
||||
--> bootp-2.3.4 (beta test release)
|
||||
12/12/93 gwr@mc.com (Gordon W. Ross)
|
||||
Fixed several more NULL references in readfile.
|
||||
Added proper length checks to option insertions.
|
||||
|
||||
--> bootp-2.3.3 (beta test release)
|
||||
12/09/93 gwr@mc.com (Gordon W. Ross)
|
||||
Added ASSERT checks to readfile.c:fill_defaults()
|
||||
|
||||
12/08/93 brezak@ch.hp.com (John Brezak)
|
||||
New Makefile.NetBSD
|
||||
Added setsid() and #ifdef TIOCNOTTY
|
||||
(bootpd.c, bootpgw.c)
|
||||
Moved #include <net/if.h> out of #ifdef SUNOS
|
||||
Fixed several multiple declaration problems
|
||||
|
||||
12/04/93 gwr@mc.com (Gordon W. Ross)
|
||||
Re-implemented Extension File support
|
||||
based on work by Jason Zions <jazz@hal.com>
|
||||
Added support for Reply-Address-Override to support
|
||||
HP clients (need reply sent to broadcast address)
|
||||
from David R. Linn <drl@vuse.vanderbilt.edu>
|
||||
|
||||
--> bootp-2.3.2 (beta test release)
|
||||
11/27/93 gwr@mc.com (Gordon W. Ross)
|
||||
Incorporated bootptest into the bootp release.
|
||||
Added ANSI function prototypes everywhere.
|
||||
|
||||
11/17/93 dpm@depend.com (David P. Maynard)
|
||||
Added automatic SLIP address determination.
|
||||
(This is NOT dynamic IP address assignment.)
|
||||
Cleaned up some type warnings from gcc.
|
||||
|
||||
11/11/93 gwr@mc.com (Gordon W. Ross)
|
||||
Works (again) with no -DSYSLOGD defined.
|
||||
Provide a default value for the subnet mask.
|
||||
More #ifdef's for SunOS specific code (lookup_hwa)
|
||||
Added a simple BOOTP gateway program: bootpgw
|
||||
Reorganized for more code sharing (with bootpgw)
|
||||
|
||||
--> bootp-2.3.1 (alpha test release)
|
||||
11/08/93 gwr@mc.com (Gordon W. Ross)
|
||||
Back-out changes to honor option structure in request
|
||||
(this needs to be a per-client option).
|
||||
Merged changes from NetBSD and Columbia versions.
|
||||
Allow host name anywhere IP address is expected.
|
||||
Add null terminators to option strings.
|
||||
Add missing symbols to dump routine, dump symbols
|
||||
in alphabetical order, one tag per line.
|
||||
|
||||
--> bootp-2.2.D (posted as patch 2)
|
||||
10/19/93 gwr@mc.com (Gordon W. Ross)
|
||||
Fix references to free memory (leads to core dumps).
|
||||
|
||||
--> bootp-2.2.C (posted as patch 1)
|
||||
10/14/93 gwr@mc.com (Gordon W. Ross)
|
||||
Fix data access alignment problems on SPARC/Solaris.
|
||||
|
||||
--> bootp-2.2.B (posted to usenet)
|
||||
10/11/93 gwr@mc.com (Gordon W. Ross)
|
||||
Allow extended-length BOOTP packets (more vendor options)
|
||||
Honor option format specified in client requests.
|
||||
Added Solaris-2.X changes from db@sunbim.be (Danny Backx).
|
||||
|
||||
All history before this point may be inaccurate. Please send
|
||||
changes if any of the credits are incorrect. -gwr
|
||||
|
||||
--> bootp-2.2+NetBSD released
|
||||
08/27/93 brezak@ch.hp.com (John Brezak)
|
||||
Added RFC 1396 support (tags 14-17)
|
||||
|
||||
--> bootp-2.2+NetBSD (version?)
|
||||
??/??/93 mckim@lerc.nasa.gov (Jim McKim)
|
||||
Ported to NetBSD (see Makefile.NetBSD)
|
||||
Set server host name in responses.
|
||||
Check all interfaces in address match routine.
|
||||
|
||||
--> bootp-2.2+FdC released
|
||||
01/27/93 <fdc@watsun.cc.columbia.edu> Frank da Cruz
|
||||
Added RFC 1395 information: Merit dump file,
|
||||
client domain name, swap server address, root path.
|
||||
|
||||
--> bootp-2.2alpha released
|
||||
11/14/91 <walt+@cmu.edu> Walter L. Wimer
|
||||
Add "td" to TFTP directory for "secure" (chroot) TFTP.
|
||||
Add "sa" tag to set explicit server address.
|
||||
Automatically determine if child of inetd.
|
||||
Use RFC 1048 format when request has magic number zero.
|
||||
Fixed various bugs. Give bootptab a separate man page.
|
||||
|
||||
--> bootp-2.1 released
|
||||
01/09/89 <walt+@cmu.edu> Walter L. Wimer
|
||||
Check world read bit on TFTP boot file.
|
||||
Add support for rfc1085 "bootfile size" tag.
|
||||
Add generic tags. Fix byte order of rfc1048 data.
|
||||
Fix various crashing bugs.
|
||||
|
||||
--> bootp-2.0 released
|
||||
07/15/88 <walt+@cmu.edu> Walter L. Wimer
|
||||
Added vendor information to conform to RFC1048.
|
||||
Adopted termcap-like file format to support above.
|
||||
Added hash table lookup instead of linear search.
|
||||
Other cleanups.
|
||||
|
||||
--> bootp-1.3(?) released
|
||||
07/24/87 <ddp@andrew.cmu.edu> Drew D. Perkins
|
||||
Modified to use syslog instead of Kovar's
|
||||
routines. Add debugging dumps. Many other fixups.
|
||||
|
||||
--> bootp-1.2(?) released
|
||||
07/30/86 David Kovar at Carnegie Mellon University
|
||||
Modified to work at CMU.
|
||||
|
||||
--> bootp-1.1 released
|
||||
01/22/86 Bill Croft at Stanford University
|
||||
Original created.
|
141
libexec/bootpd/ConvOldTab.sh
Executable file
141
libexec/bootpd/ConvOldTab.sh
Executable file
@ -0,0 +1,141 @@
|
||||
#!/bin/sh
|
||||
# convert_bootptab Jeroen.Scheerder@let.ruu.nl 02/25/94
|
||||
# This script can be used to convert bootptab files in old format
|
||||
# to new (termcap-like) bootptab files
|
||||
#
|
||||
# The old format - real entries are commented out by '###'
|
||||
#
|
||||
# Old-style bootp files consist of two sections.
|
||||
# The first section has two entries:
|
||||
# First, a line that specifies the home directory
|
||||
# (where boot file paths are relative to)
|
||||
|
||||
###/tftpboot
|
||||
|
||||
# The next non-empty non-comment line specifies the default bootfile
|
||||
|
||||
###no-file
|
||||
|
||||
# End of first section - indicated by '%%' at the start of the line
|
||||
|
||||
###%%
|
||||
|
||||
# The remainder of this file contains one line per client
|
||||
# interface with the information shown by the table headings
|
||||
# below. The host name is also tried as a suffix for the
|
||||
# bootfile when searching the home directory (that is,
|
||||
# bootfile.host)
|
||||
#
|
||||
# Note that htype is always 1, indicating the hardware type Ethernet.
|
||||
# Conversion therefore always yields ':ha=ether:'.
|
||||
#
|
||||
# host htype haddr iaddr bootfile
|
||||
#
|
||||
|
||||
###somehost 1 00:0b:ad:01:de:ad 128.128.128.128 dummy
|
||||
|
||||
# That's all for the description of the old format.
|
||||
# For the new-and-improved format, see bootptab(5).
|
||||
|
||||
set -u$DX
|
||||
|
||||
case $#
|
||||
in 2 ) OLDTAB=$1 ; NEWTAB=$2 ;;
|
||||
* ) echo "Usage: `basename $0` <Input> <Output>"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
if [ ! -r $OLDTAB ]
|
||||
then
|
||||
echo "`basename $0`: $OLDTAB does not exist or is unreadable."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if touch $NEWTAB 2> /dev/null
|
||||
then
|
||||
:
|
||||
else
|
||||
echo "`basename $0`: cannot write to $NEWTAB."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
cat << END_OF_HEADER >> $NEWTAB
|
||||
# /etc/bootptab: database for bootp server (/etc/bootpd)
|
||||
# This file was generated automagically
|
||||
|
||||
# Blank lines and lines beginning with '#' are ignored.
|
||||
#
|
||||
# Legend: (see bootptab.5)
|
||||
# first field -- hostname (not indented)
|
||||
# bf -- bootfile
|
||||
# bs -- bootfile size in 512-octet blocks
|
||||
# cs -- cookie servers
|
||||
# df -- dump file name
|
||||
# dn -- domain name
|
||||
# ds -- domain name servers
|
||||
# ef -- extension file
|
||||
# gw -- gateways
|
||||
# ha -- hardware address
|
||||
# hd -- home directory for bootfiles
|
||||
# hn -- host name set for client
|
||||
# ht -- hardware type
|
||||
# im -- impress servers
|
||||
# ip -- host IP address
|
||||
# lg -- log servers
|
||||
# lp -- LPR servers
|
||||
# ns -- IEN-116 name servers
|
||||
# ra -- reply address
|
||||
# rl -- resource location protocol servers
|
||||
# rp -- root path
|
||||
# sa -- boot server address
|
||||
# sm -- subnet mask
|
||||
# sw -- swap server
|
||||
# tc -- template host (points to similar host entry)
|
||||
# td -- TFTP directory
|
||||
# to -- time offset (seconds)
|
||||
# ts -- time servers
|
||||
# vm -- vendor magic number
|
||||
# Tn -- generic option tag n
|
||||
#
|
||||
# Be careful about including backslashes where they're needed. Weird (bad)
|
||||
# things can happen when a backslash is omitted where one is intended.
|
||||
# Also, note that generic option data must be either a string or a
|
||||
# sequence of bytes where each byte is a two-digit hex value.
|
||||
|
||||
# First, we define a global entry which specifies the stuff every host uses.
|
||||
# (Host name lookups are relative to the domain: your.domain.name)
|
||||
|
||||
END_OF_HEADER
|
||||
|
||||
# Fix up HW addresses in aa:bb:cc:dd:ee:ff and aa-bb-cc-dd-ee-ff style first
|
||||
# Then awk our stuff together
|
||||
sed -e 's/[:-]//g' < $OLDTAB | \
|
||||
nawk 'BEGIN { PART = 0 ; FIELD=0 ; BOOTPATH="unset" ; BOOTFILE="unset" }
|
||||
/^%%/ {
|
||||
PART = 1
|
||||
printf ".default:\\\n\t:ht=ether:\\\n\t:hn:\\\n\t:dn=your.domain.name:\\\n\t:ds=your,dns,servers:\\\n\t:sm=255.255.0.0:\\\n\t:hd=%s:\\\n\t:rp=%s:\\\n\t:td=%s:\\\n\t:bf=%s:\\\n\t:to=auto:\n\n", BOOTPATH, BOOTPATH, BOOTPATH, BOOTFILE
|
||||
next
|
||||
}
|
||||
/^$/ { next }
|
||||
/^#/ { next }
|
||||
{
|
||||
if ( PART == 0 && FIELD < 2 )
|
||||
{
|
||||
if ( FIELD == 0 ) BOOTPATH=$1
|
||||
if ( FIELD == 1 ) BOOTFILE=$1
|
||||
FIELD++
|
||||
}
|
||||
}
|
||||
{
|
||||
if ( PART == 1 )
|
||||
{
|
||||
HOST=$1
|
||||
HA=$3
|
||||
IP=$4
|
||||
BF=$5
|
||||
printf "%s:\\\n\t:tc=.default:\\\n\t:ha=0x%s:\\\n\t:ip=%s:\\\n\t:bf=%s:\n", HOST, HA, IP, BF
|
||||
}
|
||||
}' >> $NEWTAB
|
||||
|
||||
exit 0
|
29
libexec/bootpd/Installation
Normal file
29
libexec/bootpd/Installation
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
Installation instructions for SunOS
|
||||
|
||||
Compile the executable:
|
||||
For SunOS 4.X:
|
||||
make sunos4
|
||||
For SunOS 5.X: (Solaris)
|
||||
make sunos5
|
||||
|
||||
Install the executables:
|
||||
|
||||
make install
|
||||
|
||||
Edit (or create) the bootptab:
|
||||
(See bootptab.sample and bootptab.5 manual entry)
|
||||
edit /etc/bootptab
|
||||
|
||||
Edit /etc/services to add these two lines:
|
||||
bootps 67/udp bootp # BOOTP Server
|
||||
bootpc 68/udp # BOOTP Client
|
||||
|
||||
Edit /etc/inetd.conf to add the line:
|
||||
bootp dgram udp wait root /usr/etc/bootpd bootpd -i
|
||||
|
||||
If you compiled report.c with LOG_LOCAL2 (defined in the Makefile)
|
||||
then you may want to capture syslog messages from BOOTP by changing
|
||||
your syslog.conf file. (See the sample syslog.conf file here).
|
||||
Test the change with: logger -t test -p local2.info "message"
|
||||
|
184
libexec/bootpd/Makefile.UNIX
Normal file
184
libexec/bootpd/Makefile.UNIX
Normal file
@ -0,0 +1,184 @@
|
||||
#
|
||||
# Makefile for the BOOTP programs:
|
||||
# bootpd - BOOTP server daemon
|
||||
# bootpef - BOOTP extension file builder
|
||||
# bootpgw - BOOTP gateway daemon
|
||||
# bootptest - BOOTP tester (client)
|
||||
#
|
||||
|
||||
# OPTion DEFinitions:
|
||||
# Remove the -DVEND_CMU if you don't wish to support the "CMU vendor format"
|
||||
# in addition to the RFC1048 format. Leaving out DEBUG saves little.
|
||||
OPTDEFS= -DSYSLOG -DVEND_CMU -DDEBUG
|
||||
|
||||
# Uncomment and edit this to choose the facility code used for syslog.
|
||||
# LOG_FACILITY= "-DLOG_BOOTP=LOG_LOCAL2"
|
||||
|
||||
# SYStem DEFinitions:
|
||||
# Either uncomment some of the following, or do:
|
||||
# "make sunos4" (or "make sunos5", etc.)
|
||||
# SYSDEFS= -DSUNOS -DETC_ETHERS
|
||||
# SYSDEFS= -DSVR4
|
||||
# SYSLIBS= -lsocket -lnsl
|
||||
|
||||
# Uncomment this if your system does not provide streror(3)
|
||||
# STRERROR=strerror.o
|
||||
|
||||
# FILE DEFinitions:
|
||||
# The next few lines may be uncommented and changed to alter the default
|
||||
# filenames bootpd uses for its configuration and dump files.
|
||||
#CONFFILE= -DCONFIG_FILE=\"/usr/etc/bootptab\"
|
||||
#DUMPFILE= -DDUMPTAB_FILE=\"/usr/etc/bootpd.dump\"
|
||||
#FILEDEFS= $(CONFFILE) $(DUMPFILE)
|
||||
|
||||
# MORE DEFinitions (whatever you might want to add)
|
||||
# One might define NDEBUG (to remove "assert()" checks).
|
||||
MOREDEFS=
|
||||
|
||||
INSTALL=/usr/bin/install
|
||||
DESTDIR=
|
||||
BINDIR=/usr/etc
|
||||
MANDIR=/usr/local/man
|
||||
|
||||
CFLAGS= $(OPTDEFS) $(SYSDEFS) $(FILEDEFS) $(MOREDEFS)
|
||||
PROGS= bootpd bootpef bootpgw bootptest
|
||||
TESTS= trylook trygetif trygetea
|
||||
|
||||
all: $(PROGS)
|
||||
|
||||
tests: $(TESTS)
|
||||
|
||||
system: install
|
||||
|
||||
install: $(PROGS)
|
||||
-for f in $(PROGS) ;\
|
||||
do \
|
||||
$(INSTALL) -c -s $$f $(DESTDIR)$(BINDIR) ;\
|
||||
done
|
||||
|
||||
MAN5= bootptab.5
|
||||
MAN8= bootpd.8 bootpef.8 bootptest.8
|
||||
install.man: $(MAN5) $(MAN8)
|
||||
-for f in $(MAN5) ;\
|
||||
do \
|
||||
$(INSTALL) -c -m 644 $$f $(DESTDIR)$(MANDIR)/man5 ;\
|
||||
done
|
||||
-for f in $(MAN8) ;\
|
||||
do \
|
||||
$(INSTALL) -c -m 644 $$f $(DESTDIR)$(MANDIR)/man8 ;\
|
||||
done
|
||||
|
||||
clean:
|
||||
-rm -f core *.o
|
||||
-rm -f $(PROGS) $(TESTS)
|
||||
|
||||
distclean:
|
||||
-rm -f *.BAK *.CKP *~ .emacs*
|
||||
|
||||
#
|
||||
# Handy targets for individual systems:
|
||||
#
|
||||
|
||||
# DEC/OSF1 on the Alpha
|
||||
alpha:
|
||||
$(MAKE) SYSDEFS="-DETC_ETHERS -Dint32=int -D_SOCKADDR_LEN" \
|
||||
STRERROR=strerror.o
|
||||
|
||||
# Control Data EP/IX 1.4.3 system, BSD 4.3 mode
|
||||
epix143:
|
||||
$(MAKE) CC="cc -systype bsd43" \
|
||||
SYSDEFS="-Dconst= -D_SIZE_T -DNO_UNISTD -DUSE_BFUNCS" \
|
||||
STRERROR=strerror.o
|
||||
|
||||
# Control Data EP/IX 2.1.1 system, SVR4 mode
|
||||
epix211:
|
||||
$(MAKE) CC="cc -systype svr4" \
|
||||
SYSDEFS="-DSVR4" \
|
||||
SYSLIBS="-lsocket -lnsl"
|
||||
|
||||
# Silicon Graphics IRIX (no <sys/sockio.h>, so not SVR4)
|
||||
irix:
|
||||
$(MAKE) SYSDEFS="-DSYSV -DIRIX"
|
||||
|
||||
# SunOS 4.X
|
||||
sunos4:
|
||||
$(MAKE) SYSDEFS="-DSUNOS -DETC_ETHERS" \
|
||||
STRERROR=strerror.o
|
||||
|
||||
# Solaris 2.X (i.e. SunOS 5.X)
|
||||
sunos5:
|
||||
$(MAKE) SYSDEFS="-DSVR4 -DETC_ETHERS" \
|
||||
SYSLIBS="-lsocket -lnsl"
|
||||
|
||||
# UNIX System V Rel. 4 (also: IRIX 5.X, others)
|
||||
svr4:
|
||||
$(MAKE) SYSDEFS="-DSVR4" \
|
||||
SYSLIBS="-lsocket -lnsl"
|
||||
|
||||
#
|
||||
# How to build each program:
|
||||
#
|
||||
|
||||
OBJ_D= bootpd.o dovend.o readfile.o hash.o dumptab.o \
|
||||
lookup.o getif.o hwaddr.o tzone.o report.o $(STRERROR)
|
||||
bootpd: $(OBJ_D)
|
||||
$(CC) -o $@ $(OBJ_D) $(SYSLIBS)
|
||||
|
||||
OBJ_EF= bootpef.o dovend.o readfile.o hash.o dumptab.o \
|
||||
lookup.o hwaddr.o tzone.o report.o $(STRERROR)
|
||||
bootpef: $(OBJ_EF)
|
||||
$(CC) -o $@ $(OBJ_EF) $(SYSLIBS)
|
||||
|
||||
OBJ_GW= bootpgw.o getif.o hwaddr.o report.o $(STRERROR)
|
||||
bootpgw: $(OBJ_GW)
|
||||
$(CC) -o $@ $(OBJ_GW) $(SYSLIBS)
|
||||
|
||||
OBJ_TEST= bootptest.o print-bootp.o getif.o getether.o \
|
||||
report.o $(STRERROR)
|
||||
bootptest: $(OBJ_TEST)
|
||||
$(CC) -o $@ $(OBJ_TEST) $(SYSLIBS)
|
||||
|
||||
# This is just for testing the lookup functions.
|
||||
TRYLOOK= trylook.o lookup.o report.o $(STRERROR)
|
||||
trylook : $(TRYLOOK)
|
||||
$(CC) -o $@ $(TRYLOOK) $(SYSLIBS)
|
||||
|
||||
# This is just for testing getif.
|
||||
TRYGETIF= trygetif.o getif.o report.o $(STRERROR)
|
||||
trygetif : $(TRYGETIF)
|
||||
$(CC) -o $@ $(TRYGETIF) $(SYSLIBS)
|
||||
|
||||
# This is just for testing getether.
|
||||
TRYGETEA= trygetea.o getether.o report.o $(STRERROR)
|
||||
trygetea : $(TRYGETEA)
|
||||
$(CC) -o $@ $(TRYGETEA) $(SYSLIBS)
|
||||
|
||||
# This rule just keeps the LOG_BOOTP define localized.
|
||||
report.o : report.c
|
||||
$(CC) $(CFLAGS) $(LOG_FACILITY) -c $<
|
||||
|
||||
# Punt SunOS -target noise
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
#
|
||||
# Header file dependencies:
|
||||
#
|
||||
|
||||
bootpd.o : bootp.h bptypes.h hash.h hwaddr.h bootpd.h dovend.h
|
||||
bootpd.o : readfile.h report.h tzone.h patchlevel.h getif.h
|
||||
bootpef.o : bootp.h bptypes.h hash.h hwaddr.h bootpd.h dovend.h
|
||||
bootpef.o : readfile.h report.h tzone.h patchlevel.h
|
||||
bootpgw.o : bootp.h bptypes.h getif.h hwaddr.h report.h patchlevel.h
|
||||
bootptest.o : bootp.h bptypes.h bootptest.h getif.h patchlevel.h
|
||||
dovend.o : bootp.h bptypes.h bootpd.h hash.h hwaddr.h report.h dovend.h
|
||||
dumptab.o : bootp.h bptypes.h hash.h hwaddr.h report.h patchlevel.h bootpd.h
|
||||
getif.o : getif.h report.h
|
||||
hash.o : hash.h
|
||||
hwaddr.o : bptypes.h hwaddr.h report.h
|
||||
lookup.o : bootp.h bptypes.h lookup.h report.h
|
||||
print-bootp.o : bootp.h bptypes.h bootptest.h
|
||||
readfile.o : bootp.h bptypes.h hash.h hwaddr.h lookup.h readfile.h
|
||||
readfile.o : report.h tzone.h bootpd.h
|
||||
report.o : report.h
|
||||
tzone.o : bptypes.h report.h tzone.h
|
47
libexec/bootpd/Problems
Normal file
47
libexec/bootpd/Problems
Normal file
@ -0,0 +1,47 @@
|
||||
|
||||
Common problems and ways to work around them:
|
||||
|
||||
Bootpd complains that it "can not get IP addr for HOSTNAME"
|
||||
|
||||
If the entry is a "dummy" (not a real host) used only for
|
||||
reference by other entries, put '.' in front of the name.
|
||||
|
||||
If the entry is for a real client and the IP address for
|
||||
the client can not be found using gethostbyname(), specify
|
||||
the IP address for the client using numeric form.
|
||||
|
||||
Bootpd takes a long time to finish parsing the bootptab file:
|
||||
|
||||
Excessive startup time is usually caused by waiting for
|
||||
timeouts on failed DNS lookup operations. If this is the
|
||||
problem, find the client names for which DNS lookup fails
|
||||
and change the bootptab to specify the IP addresses for
|
||||
those clients using numeric form.
|
||||
|
||||
When bootptab entries do not specify an ip address, bootpd
|
||||
attempts to lookup the tagname as a host name to find the
|
||||
IP address. To suppress this default action, either make
|
||||
the entry a "dummy" or specify its IP numeric address.
|
||||
|
||||
If your DNS lookups work but are just slow, consider either
|
||||
running bootpd on the same machine as the DNS server or
|
||||
running a caching DNS server on the host running bootpd.
|
||||
|
||||
My huge bootptab file causes startup time to be so long that clients
|
||||
give up waiting for a reply.
|
||||
|
||||
Truly huge bootptab files make "inetd" mode impractical.
|
||||
Start bootpd in "standalone" mode when the server boots.
|
||||
|
||||
Another possibility is to run one bootpd on each network
|
||||
segment so each one can have a smaller bootptab. Only one
|
||||
instance of bootpd may run on one server, so you would need
|
||||
to use a different server for each network segment.
|
||||
|
||||
My bootp clients are given responses with a boot file name that is
|
||||
not a fully specified path.
|
||||
|
||||
Make sure the TFTP directory or home directory tags are set:
|
||||
:td=/tftpboot: (or)
|
||||
:hd=/usr/boot: (for example)
|
||||
|
133
libexec/bootpd/README
Normal file
133
libexec/bootpd/README
Normal file
@ -0,0 +1,133 @@
|
||||
|
||||
This is an enhanced version of the CMU BOOTP server which was derived
|
||||
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.
|
||||
|
||||
Please direct questions, comments, and bug reports 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 <your-address>")
|
||||
|
||||
[ From the NetBSD README file: ]
|
||||
|
||||
BOOTPD is a useful adjunct to the nfs diskless boot EPROM code.
|
||||
|
||||
The alternatives for initiating a boot of a kernel across a network
|
||||
are to use RARP protocol, or BOOTP protocol. BOOTP is more flexible;
|
||||
it allows additional items of information to be returned to the
|
||||
booting client; it also supports booting across gateways.
|
||||
|
||||
[ From the CMU README file: ]
|
||||
|
||||
Notes:
|
||||
1) BOOTP was originally designed and implemented by Bill Croft at Stanford.
|
||||
Much of the credit for the ideas and the code goes to him. We've added
|
||||
code to support the vendor specific area of the packet as specified in
|
||||
RFC1048. We've also improved the host lookup algorithm and added some
|
||||
extra logging.
|
||||
|
||||
2) The server now uses syslog to do logging. Specifically it uses the 4.3bsd
|
||||
version. I've #ifdef'd all of these calls. If you are running 4.2 you
|
||||
should compile without the -DSYSLOG switch.
|
||||
|
||||
3) You must update your /etc/services file to contain the following two lines:
|
||||
bootps 67/udp bootp # BOOTP Server
|
||||
bootpc 68/udp # BOOTP Client
|
||||
|
||||
4) Edit the bootptab. It has some explanitory comments, and there
|
||||
is a manual entry describing its format (bootptab.5)
|
||||
If you have any questions, just let us know.
|
||||
|
||||
Construction:
|
||||
[ See the file Installation which is more up-to-date. -gwr ]
|
||||
|
||||
Make sure all of the files exist first. If anything is missing,
|
||||
please contact either Walt Wimer or Drew Perkins by E-mail or phone.
|
||||
Addresses and phone numbers are listed below.
|
||||
|
||||
Type 'make'. The options at present are: -DSYSLOG which enables logging
|
||||
code, -DDEBUG which enables table dumping via signals, and -DVEND_CMU
|
||||
which enables the CMU extensions for CMU PC/IP.
|
||||
|
||||
Edit the bootptab. The man page and the comments in the file should
|
||||
explain how to go about doing so. If you have any problems, let me know.
|
||||
|
||||
Type 'make install'. This should put all of the files in the right place.
|
||||
|
||||
Edit your /etc/rc.local or /etc/inetd.conf file to start up bootpd upon
|
||||
reboot. The following is a sample /etc/inetd.conf entry:
|
||||
# BOOTP server
|
||||
bootps dgram udp wait root /usr/etc/bootpd bootpd -i
|
||||
|
||||
Care and feeding:
|
||||
If you change the interface cards on your host or add new hosts you will
|
||||
need to update /etc/bootptab. Just edit it as before. Once you write
|
||||
it back out, bootpd will notice that there is a new copy and will
|
||||
reread it the next time it gets a request.
|
||||
|
||||
If your bootp clients don't get a response then several things might be
|
||||
wrong. Most often, the entry for that host is not in the database.
|
||||
Check the hardware address and then check the entry and make sure
|
||||
everything is right. Other problems include the server machine crashing,
|
||||
bad cables, and the like. If your network is very congested you should
|
||||
try making your bootp clients send additional requests before giving up.
|
||||
|
||||
|
||||
November 7, 1988
|
||||
|
||||
|
||||
Walter L. Wimer Drew D. Perkins
|
||||
ww0n@andrew.cmu.edu ddp@andrew.cmu.edu
|
||||
(412) 268-6252 (412) 268-8576
|
||||
|
||||
4910 Forbes Ave
|
||||
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
|
||||
bootpd.h header for above (and others)
|
||||
bootpef.8 Manual page for bootpef
|
||||
bootpef.c BOOTP extension file compiler
|
||||
bootpgw.c BOOTP gateway main module
|
||||
bootptab.5 A manual describing the bootptab format
|
||||
bootptab.cmu A sample database file for the server
|
||||
bootptab.mcs Another sample from <gwr@mc.com>
|
||||
bootptest.8 Manual page for bootptest
|
||||
bootptest.c BOOTP test program (fake client)
|
||||
bootptest.h header for above
|
||||
dovend.c Vendor Option builder (for bootpd, bootpef)
|
||||
dovend.h header for above
|
||||
dumptab.c Implements debugging dump for bootpd
|
||||
getether.c For bootptest (not used yet)
|
||||
getif.c Get network interface info.
|
||||
getif.h header for above
|
||||
hash.c The hash table module
|
||||
hash.h header for above
|
||||
hwaddr.c Hardware address support
|
||||
hwaddr.h header for above
|
||||
lookup.c Internet Protocol address lookup
|
||||
lookup.h header for above
|
||||
patchlevel.h Holds version numbers
|
||||
print-bootp.c Prints BOOTP packets (taken from BSD tcpdump)
|
||||
readfile.c The configuration file-reading routines
|
||||
readfile.h header for above
|
||||
report.c Does syslog-style messages
|
||||
report.h header for above
|
||||
strerror.c Library errno-to-string (for systems lacking it)
|
||||
syslog.conf Sample config file for syslogd(8)
|
||||
syslog.h For systems that lack syslog(3)
|
||||
try*.c Test programs (for debugging)
|
||||
tzone.c Get timezone offset
|
||||
tzone.h header for above
|
147
libexec/bootpd/bootp.h
Normal file
147
libexec/bootpd/bootp.h
Normal file
@ -0,0 +1,147 @@
|
||||
/************************************************************************
|
||||
Copyright 1988, 1991 by Carnegie Mellon University
|
||||
|
||||
All Rights Reserved
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted, provided
|
||||
that the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation, and that the name of Carnegie Mellon University not be used
|
||||
in advertising or publicity pertaining to distribution of the software
|
||||
without specific, written prior permission.
|
||||
|
||||
CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
|
||||
IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
SOFTWARE.
|
||||
************************************************************************/
|
||||
|
||||
/*
|
||||
* Bootstrap Protocol (BOOTP). RFC951 and RFC1395.
|
||||
*
|
||||
* $Id: bootp.h,v 1.1.1.1 1994/09/10 14:44:54 csgr Exp $
|
||||
*
|
||||
*
|
||||
* This file specifies the "implementation-independent" BOOTP protocol
|
||||
* information which is common to both client and server.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bptypes.h" /* for int32, u_int32 */
|
||||
|
||||
#define BP_CHADDR_LEN 16
|
||||
#define BP_SNAME_LEN 64
|
||||
#define BP_FILE_LEN 128
|
||||
#define BP_VEND_LEN 64
|
||||
#define BP_MINPKTSZ 300 /* to check sizeof(struct bootp) */
|
||||
|
||||
struct bootp {
|
||||
unsigned char bp_op; /* packet opcode type */
|
||||
unsigned char bp_htype; /* hardware addr type */
|
||||
unsigned char bp_hlen; /* hardware addr length */
|
||||
unsigned char bp_hops; /* gateway hops */
|
||||
unsigned int32 bp_xid; /* transaction ID */
|
||||
unsigned short bp_secs; /* seconds since boot began */
|
||||
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 */
|
||||
struct in_addr bp_giaddr; /* gateway IP address */
|
||||
unsigned char bp_chaddr[BP_CHADDR_LEN]; /* client hardware address */
|
||||
char bp_sname[BP_SNAME_LEN]; /* server host name */
|
||||
char bp_file[BP_FILE_LEN]; /* boot file name */
|
||||
unsigned char bp_vend[BP_VEND_LEN]; /* vendor-specific area */
|
||||
/* note that bp_vend can be longer, extending to end of packet. */
|
||||
};
|
||||
|
||||
/*
|
||||
* UDP port numbers, server and client.
|
||||
*/
|
||||
#define IPPORT_BOOTPS 67
|
||||
#define IPPORT_BOOTPC 68
|
||||
|
||||
#define BOOTREPLY 2
|
||||
#define BOOTREQUEST 1
|
||||
|
||||
/*
|
||||
* Hardware types from Assigned Numbers RFC.
|
||||
*/
|
||||
#define HTYPE_ETHERNET 1
|
||||
#define HTYPE_EXP_ETHERNET 2
|
||||
#define HTYPE_AX25 3
|
||||
#define HTYPE_PRONET 4
|
||||
#define HTYPE_CHAOS 5
|
||||
#define HTYPE_IEEE802 6
|
||||
#define HTYPE_ARCNET 7
|
||||
|
||||
/*
|
||||
* Vendor magic cookie (v_magic) for CMU
|
||||
*/
|
||||
#define VM_CMU "CMU"
|
||||
|
||||
/*
|
||||
* Vendor magic cookie (v_magic) for RFC1048
|
||||
*/
|
||||
#define VM_RFC1048 { 99, 130, 83, 99 }
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Tag values used to specify what information is being supplied in
|
||||
* the vendor (options) data area of the packet.
|
||||
*/
|
||||
/* RFC 1048 */
|
||||
#define TAG_END ((unsigned char) 255)
|
||||
#define TAG_PAD ((unsigned char) 0)
|
||||
#define TAG_SUBNET_MASK ((unsigned char) 1)
|
||||
#define TAG_TIME_OFFSET ((unsigned char) 2)
|
||||
#define TAG_GATEWAY ((unsigned char) 3)
|
||||
#define TAG_TIME_SERVER ((unsigned char) 4)
|
||||
#define TAG_NAME_SERVER ((unsigned char) 5)
|
||||
#define TAG_DOMAIN_SERVER ((unsigned char) 6)
|
||||
#define TAG_LOG_SERVER ((unsigned char) 7)
|
||||
#define TAG_COOKIE_SERVER ((unsigned char) 8)
|
||||
#define TAG_LPR_SERVER ((unsigned char) 9)
|
||||
#define TAG_IMPRESS_SERVER ((unsigned char) 10)
|
||||
#define TAG_RLP_SERVER ((unsigned char) 11)
|
||||
#define TAG_HOST_NAME ((unsigned char) 12)
|
||||
#define TAG_BOOT_SIZE ((unsigned char) 13)
|
||||
/* RFC 1395 */
|
||||
#define TAG_DUMP_FILE ((unsigned char) 14)
|
||||
#define TAG_DOMAIN_NAME ((unsigned char) 15)
|
||||
#define TAG_SWAP_SERVER ((unsigned char) 16)
|
||||
#define TAG_ROOT_PATH ((unsigned char) 17)
|
||||
/* RFC 1497 */
|
||||
#define TAG_EXTEN_FILE ((unsigned char) 18)
|
||||
/* RFC 1533 */
|
||||
#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 */
|
||||
|
||||
|
||||
/*
|
||||
* "vendor" data permitted for CMU bootp clients.
|
||||
*/
|
||||
|
||||
struct cmu_vend {
|
||||
char v_magic[4]; /* magic number */
|
||||
unsigned int32 v_flags; /* flags/opcodes, etc. */
|
||||
struct in_addr v_smask; /* Subnet mask */
|
||||
struct in_addr v_dgate; /* Default gateway */
|
||||
struct in_addr v_dns1, v_dns2; /* Domain name servers */
|
||||
struct in_addr v_ins1, v_ins2; /* IEN-116 name servers */
|
||||
struct in_addr v_ts1, v_ts2; /* Time servers */
|
||||
int32 v_unused[6]; /* currently unused */
|
||||
};
|
||||
|
||||
|
||||
/* v_flags values */
|
||||
#define VF_SMASK 1 /* Subnet mask field contains valid data */
|
305
libexec/bootpd/bootpd.8
Normal file
305
libexec/bootpd/bootpd.8
Normal file
@ -0,0 +1,305 @@
|
||||
.\" Copyright (c) 1988, 1989, 1991 Carnegie Mellon University
|
||||
.\"
|
||||
.\" $Header: /home/ncvs/src/usr.sbin/bootpd/bootpd.8,v 1.1.1.1 1994/09/10 14:44:54 csgr Exp $
|
||||
.\"
|
||||
.TH BOOTPD 8 "November 06, 1993" "Carnegie Mellon University"
|
||||
.SH NAME
|
||||
bootpd, bootpgw \- Internet Boot Protocol server/gateway
|
||||
.SH SYNOPSIS
|
||||
.B bootpd
|
||||
[
|
||||
.B \-i
|
||||
.B \-s
|
||||
.B \-t
|
||||
timeout
|
||||
.B \-d
|
||||
level
|
||||
.B \-c
|
||||
chdir\-path
|
||||
]
|
||||
[
|
||||
.I bootptab
|
||||
[
|
||||
.I dumpfile
|
||||
] ]
|
||||
.br
|
||||
.B bootpgw
|
||||
[
|
||||
.B \-i
|
||||
.B \-s
|
||||
.B \-t
|
||||
timeout
|
||||
.B \-d
|
||||
level
|
||||
] server
|
||||
.SH DESCRIPTION
|
||||
.I Bootpd
|
||||
implements an Internet Bootstrap Protocol (BOOTP) server as defined in
|
||||
RFC951, RFC1532, and RFC1533.
|
||||
.I Bootpgw
|
||||
implements a simple BOOTP gateway which can be used to forward
|
||||
requests and responses between clients on one subnet and a
|
||||
BOOTP server (i.e.
|
||||
.IR bootpd )
|
||||
on another subnet. While either
|
||||
.I bootpd
|
||||
or
|
||||
.I bootpgw
|
||||
will forward BOOTREPLY packets, only
|
||||
.I bootpgw
|
||||
will forward BOOTREQUEST packets.
|
||||
.PP
|
||||
One host on each network segment is normally configured to run either
|
||||
.I bootpd
|
||||
or
|
||||
.I bootpgw
|
||||
from
|
||||
.I inetd
|
||||
by including one of the following lines in the file
|
||||
.IR /etc/inetd.conf :
|
||||
.IP
|
||||
bootps dgram udp wait root /etc/bootpd bootpd bootptab
|
||||
.br
|
||||
bootps dgram udp wait root /etc/bootpgw bootpgw server
|
||||
.PP
|
||||
This mode of operation is referred to as "inetd mode" and causes
|
||||
.I bootpd
|
||||
(or
|
||||
.IR bootpgw )
|
||||
to be started only when a boot request arrives. If it does not
|
||||
receive another packet within fifteen minutes of the last one
|
||||
it received, it will exit to conserve system resources. The
|
||||
.B \-t
|
||||
option controls this timeout (see OPTIONS).
|
||||
.PP
|
||||
It is also possible to run
|
||||
.I bootpd
|
||||
(or
|
||||
.IR bootpgw )
|
||||
in "standalone mode" (without
|
||||
.IR inetd )
|
||||
by simply invoking it from a shell like any other regular command.
|
||||
Standalone mode is particularly useful when
|
||||
.I bootpd
|
||||
is used with a large configuration database, where the start up
|
||||
delay might otherwise prevent timely response to client requests.
|
||||
(Automatic start up in standalone mode can be done by invoking
|
||||
.I bootpd
|
||||
from within
|
||||
.IR /etc/rc.local ,
|
||||
for example.)
|
||||
Standalone mode is less useful for
|
||||
.I bootgw
|
||||
which
|
||||
has very little start up delay because
|
||||
it does not read a configuration file.
|
||||
.PP
|
||||
Either program automatically detects whether it was invoked from inetd
|
||||
or from a shell and automatically selects the appropriate mode.
|
||||
The
|
||||
.B \-s
|
||||
or
|
||||
.B \-i
|
||||
option may be used to force standalone or inetd mode respectively
|
||||
(see OPTIONS).
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BI \-t \ timeout
|
||||
Specifies the
|
||||
.I timeout
|
||||
value (in minutes) that a
|
||||
.I bootpd
|
||||
or
|
||||
.I bootpgw
|
||||
process will wait for a BOOTP packet before exiting.
|
||||
If no packets are recieved for
|
||||
.I timeout
|
||||
seconds, then the program will exit.
|
||||
A timeout value of zero means "run forever".
|
||||
In standalone mode, this option is forced to zero.
|
||||
.TP
|
||||
.BI \-d \ debug\-level
|
||||
Sets the
|
||||
.I debug\-level
|
||||
variable that controls the amount of debugging messages generated.
|
||||
For example, -d4 or -d 4 will set the debugging level to 4.
|
||||
For compatibility with older versions of
|
||||
.IR bootpd ,
|
||||
omitting the numeric parameter (i.e. just -d) will
|
||||
simply increment the debug level by one.
|
||||
.TP
|
||||
.BI \-c \ chdir\-path
|
||||
Sets the current directory used by
|
||||
.I bootpd
|
||||
while checking the existence and size of client boot files. This is
|
||||
useful when client boot files are specified as relative pathnames, and
|
||||
.I bootpd
|
||||
needs to use the same current directory as the TFTP server
|
||||
(typically /tftpboot). This option is not recoginzed by
|
||||
.IR bootpgw .
|
||||
.TP
|
||||
.B \-i
|
||||
Force inetd mode. This option is obsolete, but remains for
|
||||
compatibility with older versions of
|
||||
.IR bootpd .
|
||||
.TP
|
||||
.B \-s
|
||||
Force standalone mode. This option is obsolete, but remains for
|
||||
compatibility with older versions of
|
||||
.IR bootpd .
|
||||
.TP
|
||||
.I bootptab
|
||||
Specifies the name of the configuration file from which
|
||||
.I bootpd
|
||||
loads its database of known clients and client options
|
||||
.RI ( bootpd
|
||||
only).
|
||||
.TP
|
||||
.I dumpfile
|
||||
Specifies the name of the file that
|
||||
.I bootpd
|
||||
will dump its internal database into when it receives a
|
||||
SIGUSR1 signal
|
||||
.RI ( bootpd
|
||||
only). This option is only recognized if
|
||||
.I bootpd
|
||||
was compiled with the -DDEBUG flag.
|
||||
.TP
|
||||
.I server
|
||||
Specifies the name of a BOOTP server to which
|
||||
.I bootpgw
|
||||
will forward all BOOTREQUEST packets it receives
|
||||
.RI ( bootpgw
|
||||
only).
|
||||
.SH OPERATION
|
||||
.PP
|
||||
Both
|
||||
.I bootpd
|
||||
and
|
||||
.I bootpgw
|
||||
operate similarly in that both listen for any packets sent to the
|
||||
.I bootps
|
||||
port, and both simply forward any BOOTREPLY packets.
|
||||
They differ in their handling of BOOTREQUEST packets.
|
||||
.PP
|
||||
When
|
||||
.I bootpgw
|
||||
is started, it determines the address of a BOOTP server
|
||||
whose name is provided as a command line parameter. When
|
||||
.I bootpgw
|
||||
receives a BOOTREQUEST packet, it sets the "gateway address"
|
||||
and "hop count" fields in the packet and forwards the packet
|
||||
to the BOOTP server at the address determined earlier.
|
||||
Requests are forwarded only if they indicate that
|
||||
the client has been waiting for at least three seconds.
|
||||
.PP
|
||||
When
|
||||
.I bootpd
|
||||
is started it reads a configuration file, (normally
|
||||
.IR /etc/bootptab )
|
||||
that initializes the internal database of known clients and client
|
||||
options. This internal database is reloaded
|
||||
from the configuration file when
|
||||
.I bootpd
|
||||
receives a hangup signal (SIGHUP) or when it discovers that the
|
||||
configuration file has changed.
|
||||
.PP
|
||||
When
|
||||
.I bootpd
|
||||
receives a BOOTREQUEST packet, it
|
||||
.\" checks the modification time of the
|
||||
.\" configuration file and reloads the database if necessary. Then it
|
||||
looks for a database entry matching the client request.
|
||||
If the client is known,
|
||||
.I bootpd
|
||||
composes a BOOTREPLY packet using the database entry found above,
|
||||
and sends the reply to the client (possibly using a gateway).
|
||||
If the client is unknown, the request is discarded
|
||||
(with a notice if debug > 0).
|
||||
.PP
|
||||
If
|
||||
.I bootpd
|
||||
is compiled with the -DDEBUG option, receipt of a SIGUSR1 signal causes
|
||||
it to dump its internal database to the file
|
||||
.I /etc/bootpd.dump
|
||||
or the dumpfile specified as a command line parameter.
|
||||
.PP
|
||||
During initialization, both programs
|
||||
determine the UDP port numbers to be used by calling
|
||||
.I getservbyname
|
||||
(which nomally uses
|
||||
.IR /etc/services).
|
||||
Two service names (and port numbers) are used:
|
||||
.IP
|
||||
bootps \- BOOTP Server listening port
|
||||
.br
|
||||
bootpc \- BOOTP Client destination port
|
||||
.LP
|
||||
If the port numbers cannot
|
||||
be determined using
|
||||
.I getservbyname
|
||||
then the values default to boopts=67 and bootpc=68.
|
||||
.SH FILES
|
||||
.TP 20
|
||||
/etc/bootptab
|
||||
Database file read by
|
||||
.IR bootpd .
|
||||
.TP
|
||||
/etc/bootpd.dump
|
||||
Debugging dump file created by
|
||||
.IR bootpd .
|
||||
.TP
|
||||
/etc/services
|
||||
Internet service numbers.
|
||||
.TP
|
||||
/tftpboot
|
||||
Current directory typically used by the TFTP server and
|
||||
.IR bootpd .
|
||||
|
||||
.SH BUGS
|
||||
Individual host entries must not exceed 1024 characters.
|
||||
|
||||
.SH CREDITS
|
||||
.PP
|
||||
This distribution is currently maintained by
|
||||
Walter L. Wimer <walt+@cmu.edu>.
|
||||
.PP
|
||||
The original BOOTP server was created by
|
||||
Bill Croft at Stanford University in January 1986.
|
||||
.PP
|
||||
The current version of
|
||||
.I bootpd
|
||||
is primarily the work of David Kovar,
|
||||
Drew D. Perkins, and Walter L. Wimer,
|
||||
at Carnegie Mellon University.
|
||||
.TP
|
||||
Enhancements and bug\-fixes have been contributed by:
|
||||
(in alphabetical order)
|
||||
.br
|
||||
Danny Backx <db@sunbim.be>
|
||||
.br
|
||||
John Brezak <brezak@ch.hp.com>
|
||||
.br
|
||||
Frank da Cruz <fdc@cc.columbia.edu>
|
||||
.br
|
||||
David R. Linn <drl@vuse.vanderbilt.edu>
|
||||
.br
|
||||
Jim McKim <mckim@lerc.nasa.gov>
|
||||
.br
|
||||
Gordon W. Ross <gwr@mc.com>
|
||||
.br
|
||||
Jason Zions <jazz@hal.com>
|
||||
.SH "SEE ALSO"
|
||||
.LP
|
||||
bootptab(5), inetd(8), tftpd(8)
|
||||
.LP
|
||||
DARPA Internet Request For Comments:
|
||||
.TP 10
|
||||
RFC951
|
||||
Bootstrap Protocol
|
||||
.TP 10
|
||||
RFC1532
|
||||
Clarifications and Extensions for the Bootstrap Protocol
|
||||
.TP 10
|
||||
RFC1533
|
||||
DHCP Options and BOOTP Vendor Extensions
|
1380
libexec/bootpd/bootpd.c
Normal file
1380
libexec/bootpd/bootpd.c
Normal file
File diff suppressed because it is too large
Load Diff
211
libexec/bootpd/bootpd.h
Normal file
211
libexec/bootpd/bootpd.h
Normal file
@ -0,0 +1,211 @@
|
||||
/************************************************************************
|
||||
Copyright 1988, 1991 by Carnegie Mellon University
|
||||
|
||||
All Rights Reserved
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted, provided
|
||||
that the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation, and that the name of Carnegie Mellon University not be used
|
||||
in advertising or publicity pertaining to distribution of the software
|
||||
without specific, written prior permission.
|
||||
|
||||
CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
|
||||
IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
SOFTWARE.
|
||||
************************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* bootpd.h -- common header file for all the modules of the bootpd program.
|
||||
*/
|
||||
|
||||
#include "bptypes.h"
|
||||
#include "hash.h"
|
||||
#include "hwaddr.h"
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef PRIVATE
|
||||
#define PRIVATE static
|
||||
#endif
|
||||
|
||||
#ifndef SIGUSR1
|
||||
#define SIGUSR1 30 /* From 4.3 <signal.h> */
|
||||
#endif
|
||||
|
||||
#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.
|
||||
*/
|
||||
#define get_network_errmsg get_errmsg
|
||||
|
||||
|
||||
/*
|
||||
* Data structure used to hold an arbitrary-lengthed list of IP addresses.
|
||||
* The list may be shared among multiple hosts by setting the linkcount
|
||||
* appropriately.
|
||||
*/
|
||||
|
||||
struct in_addr_list {
|
||||
unsigned int linkcount, addrcount;
|
||||
struct in_addr addr[1]; /* Dynamically extended */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Data structures used to hold shared strings and shared binary data.
|
||||
* The linkcount must be set appropriately.
|
||||
*/
|
||||
|
||||
struct shared_string {
|
||||
unsigned int linkcount;
|
||||
char string[1]; /* Dynamically extended */
|
||||
};
|
||||
|
||||
struct shared_bindata {
|
||||
unsigned int linkcount, length;
|
||||
byte data[1]; /* Dynamically extended */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Flag structure which indicates which symbols have been defined for a
|
||||
* given host. This information is used to determine which data should or
|
||||
* should not be reported in the bootp packet vendor info field.
|
||||
*/
|
||||
|
||||
struct flag {
|
||||
unsigned bootfile :1,
|
||||
bootserver :1,
|
||||
bootsize :1,
|
||||
bootsize_auto :1,
|
||||
cookie_server :1,
|
||||
domain_server :1,
|
||||
gateway :1,
|
||||
generic :1,
|
||||
haddr :1,
|
||||
homedir :1,
|
||||
htype :1,
|
||||
impress_server :1,
|
||||
iaddr :1,
|
||||
log_server :1,
|
||||
lpr_server :1,
|
||||
name_server :1,
|
||||
name_switch :1,
|
||||
rlp_server :1,
|
||||
send_name :1,
|
||||
subnet_mask :1,
|
||||
tftpdir :1,
|
||||
time_offset :1,
|
||||
time_server :1,
|
||||
dump_file :1,
|
||||
domain_name :1,
|
||||
swap_server :1,
|
||||
root_path :1,
|
||||
exten_file :1,
|
||||
reply_addr :1,
|
||||
nis_domain :1,
|
||||
nis_server :1,
|
||||
ntp_server :1,
|
||||
exec_file :1,
|
||||
msg_size :1,
|
||||
min_wait :1,
|
||||
/* XXX - Add new tags here */
|
||||
vm_cookie :1;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The flags structure contains TRUE flags for all the fields which
|
||||
* are considered valid, regardless of whether they were explicitly
|
||||
* specified or indirectly inferred from another entry.
|
||||
*
|
||||
* The gateway and the various server fields all point to a shared list of
|
||||
* IP addresses.
|
||||
*
|
||||
* The hostname, home directory, and bootfile are all shared strings.
|
||||
*
|
||||
* The generic data field is a shared binary data structure. It is used to
|
||||
* hold future RFC1048 vendor data until bootpd is updated to understand it.
|
||||
*
|
||||
* The vm_cookie field specifies the four-octet vendor magic cookie to use
|
||||
* if it is desired to always send the same response to a given host.
|
||||
*
|
||||
* Hopefully, the rest is self-explanatory.
|
||||
*/
|
||||
|
||||
struct host {
|
||||
unsigned linkcount; /* hash list inserts */
|
||||
struct flag flags; /* ALL valid fields */
|
||||
struct in_addr_list *cookie_server,
|
||||
*domain_server,
|
||||
*gateway,
|
||||
*impress_server,
|
||||
*log_server,
|
||||
*lpr_server,
|
||||
*name_server,
|
||||
*rlp_server,
|
||||
*time_server,
|
||||
*nis_server,
|
||||
*ntp_server;
|
||||
struct shared_string *bootfile,
|
||||
*hostname,
|
||||
*domain_name,
|
||||
*homedir,
|
||||
*tftpdir,
|
||||
*dump_file,
|
||||
*exten_file,
|
||||
*root_path,
|
||||
*nis_domain,
|
||||
*exec_file;
|
||||
struct shared_bindata *generic;
|
||||
byte vm_cookie[4],
|
||||
htype, /* RFC826 says this should be 16-bits but
|
||||
RFC951 only allocates 1 byte. . . */
|
||||
haddr[MAXHADDRLEN];
|
||||
int32 time_offset;
|
||||
unsigned int32 bootsize,
|
||||
msg_size,
|
||||
min_wait;
|
||||
struct in_addr bootserver,
|
||||
iaddr,
|
||||
swap_server,
|
||||
reply_addr,
|
||||
subnet_mask;
|
||||
/* XXX - Add new tags here (or above as appropriate) */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Variables shared among modules.
|
||||
*/
|
||||
|
||||
extern int debug;
|
||||
extern char *bootptab;
|
||||
extern char *progname;
|
||||
|
||||
extern u_char vm_cmu[4];
|
||||
extern u_char vm_rfc1048[4];
|
||||
|
||||
extern hash_tbl *hwhashtable;
|
||||
extern hash_tbl *iphashtable;
|
||||
extern hash_tbl *nmhashtable;
|
||||
|
395
libexec/bootpd/bootptab.5
Normal file
395
libexec/bootpd/bootptab.5
Normal file
@ -0,0 +1,395 @@
|
||||
.\" Copyright (c) 1988, 1989, 1991 Carnegie Mellon University
|
||||
.\"
|
||||
.\" $Header: /home/ncvs/src/usr.sbin/bootpd/bootptab.5,v 1.1.1.1 1994/09/10 14:44:54 csgr Exp $
|
||||
.\"
|
||||
.TH BOOTPTAB 5 "October 31, 1991" "Carnegie Mellon University"
|
||||
.UC 6
|
||||
|
||||
.SH NAME
|
||||
bootptab \- Internet Bootstrap Protocol server database
|
||||
.SH DESCRIPTION
|
||||
The
|
||||
.I bootptab
|
||||
file is the configuration database file for
|
||||
.IR bootpd ,
|
||||
the Internet Bootstrap Protocol server.
|
||||
It's format is similar to that of
|
||||
.IR termcap (5)
|
||||
in which two-character case-sensitive tag symbols are used to
|
||||
represent host parameters. These parameter declarations are separated by
|
||||
colons (:), with a general format of:
|
||||
.PP
|
||||
.I " hostname:tg=value. . . :tg=value. . . :tg=value. . . ."
|
||||
.PP
|
||||
where
|
||||
.I hostname
|
||||
is the actual name of a bootp client (or a "dummy entry"), and
|
||||
.I tg
|
||||
is a two-character tag symbol. Dummy entries have an invalid hostname
|
||||
(one with a "." as the first character) and are used to provide
|
||||
default values used by other entries via the
|
||||
.B tc=.dummy-entry
|
||||
mechanism. Most tags must be followed by an equals-sign
|
||||
and a value as above. Some may also appear in a boolean form with no
|
||||
value (i.e.
|
||||
.RI : tg :).
|
||||
The currently recognized tags are:
|
||||
.PP
|
||||
.br
|
||||
bf Bootfile
|
||||
.br
|
||||
bs Bootfile size in 512-octet blocks
|
||||
.br
|
||||
cs Cookie server address list
|
||||
.br
|
||||
df Merit dump file
|
||||
.br
|
||||
dn Domain name
|
||||
.br
|
||||
ds Domain name server address list
|
||||
.br
|
||||
ef Extension file
|
||||
.br
|
||||
gw Gateway address list
|
||||
.br
|
||||
ha Host hardware address
|
||||
.br
|
||||
hd Bootfile home directory
|
||||
.br
|
||||
hn Send client's hostname to client
|
||||
.br
|
||||
ht Host hardware type (see Assigned Numbers RFC)
|
||||
.br
|
||||
im Impress server address list
|
||||
.br
|
||||
ip Host IP address
|
||||
.br
|
||||
lg Log server address list
|
||||
.br
|
||||
lp LPR server address list
|
||||
.br
|
||||
ns IEN-116 name server address list
|
||||
.br
|
||||
nt NTP (time) Server (RFC 1129)
|
||||
.br
|
||||
ra Reply address override
|
||||
.br
|
||||
rl Resource location protocol server address list
|
||||
.br
|
||||
rp Root path to mount as root
|
||||
.br
|
||||
sa TFTP server address client should use
|
||||
.br
|
||||
sm Host subnet mask
|
||||
.br
|
||||
sw Swap server address
|
||||
.br
|
||||
tc Table continuation (points to similar "template" host entry)
|
||||
.br
|
||||
td TFTP root directory used by "secure" TFTP servers
|
||||
.br
|
||||
to Time offset in seconds from UTC
|
||||
.br
|
||||
ts Time server address list
|
||||
.br
|
||||
vm Vendor magic cookie selector
|
||||
.br
|
||||
yd YP (NIS) domain name
|
||||
.br
|
||||
ys YP (NIS) server address
|
||||
|
||||
.PP
|
||||
There is also a generic tag,
|
||||
.RI T n ,
|
||||
where
|
||||
.I n
|
||||
is an RFC1084 vendor field tag number. Thus it is possible to immediately
|
||||
take advantage of future extensions to RFC1084 without being forced to modify
|
||||
.I bootpd
|
||||
first. Generic data may be represented as either a stream of hexadecimal
|
||||
numbers or as a quoted string of ASCII characters. The length of the generic
|
||||
data is automatically determined and inserted into the proper field(s) of the
|
||||
RFC1084-style bootp reply.
|
||||
.PP
|
||||
The following tags take a whitespace-separated list of IP addresses:
|
||||
.BR cs ,
|
||||
.BR ds ,
|
||||
.BR gw ,
|
||||
.BR im ,
|
||||
.BR lg ,
|
||||
.BR lp ,
|
||||
.BR ns ,
|
||||
.BR nt ,
|
||||
.BR ra ,
|
||||
.BR rl ,
|
||||
and
|
||||
.BR ts .
|
||||
The
|
||||
.BR ip ,
|
||||
.BR sa ,
|
||||
.BR sw ,
|
||||
.BR sm ,
|
||||
and
|
||||
.B ys
|
||||
tags each take a single IP address.
|
||||
All IP addresses are specified in standard Internet "dot" notation
|
||||
and may use decimal, octal, or hexadecimal numbers
|
||||
(octal numbers begin with 0, hexadecimal numbers begin with '0x' or '0X').
|
||||
Any IP addresses may alternatively be specified as a hostname, causing
|
||||
.I bootpd
|
||||
to lookup the IP address for that host name using gethostbyname(3).
|
||||
If the
|
||||
.B ip
|
||||
tag is not specified,
|
||||
.I bootpd
|
||||
will determine the IP address using the entry name as the host name.
|
||||
(Dummy entries use an invalid host name to avoid automatic IP lookup.)
|
||||
.PP
|
||||
The
|
||||
.B ht
|
||||
tag specifies the hardware type code as either an unsigned decimal, octal, or
|
||||
hexadecimal integer or one of the following symbolic names:
|
||||
.B ethernet
|
||||
or
|
||||
.B ether
|
||||
for 10Mb Ethernet,
|
||||
.B ethernet3
|
||||
or
|
||||
.B ether3
|
||||
for 3Mb experimental Ethernet,
|
||||
.BR ieee802 ,
|
||||
.BR tr ,
|
||||
or
|
||||
.B token-ring
|
||||
for IEEE 802 networks,
|
||||
.B pronet
|
||||
for Proteon ProNET Token Ring, or
|
||||
.BR chaos ,
|
||||
.BR arcnet ,
|
||||
or
|
||||
.B ax.25
|
||||
for Chaos, ARCNET, and AX.25 Amateur Radio networks, respectively.
|
||||
The
|
||||
.B ha
|
||||
tag takes a hardware address which may be specified as a host name
|
||||
or in numeric form. Note that the numeric form
|
||||
.I must
|
||||
be specified in hexadecimal; optional periods and/or a leading '0x' may be
|
||||
included for readability. The
|
||||
.B ha
|
||||
tag must be preceded by the
|
||||
.B ht
|
||||
tag (either explicitly or implicitly; see
|
||||
.B tc
|
||||
below).
|
||||
If the hardware address is not specified and the type is specified
|
||||
as either "ethernet" or "ieee802", then
|
||||
.I bootpd
|
||||
will try to determine the hardware address using ether_hton(3).
|
||||
.PP
|
||||
The hostname, home directory, and bootfile are ASCII strings which may be
|
||||
optionally surrounded by double quotes ("). The client's request and the
|
||||
values of the
|
||||
.B hd
|
||||
and
|
||||
.B bf
|
||||
symbols determine how the server fills in the bootfile field of the bootp
|
||||
reply packet.
|
||||
.PP
|
||||
If the client provides a file name it is left as is.
|
||||
Otherwise, if the
|
||||
.B bf
|
||||
option is specified its value is copied into the reply packet.
|
||||
If the
|
||||
.B hd
|
||||
option is specified as well, its value is prepended to the
|
||||
boot file copied into the reply packet.
|
||||
The existence of the boot file is checked only if the
|
||||
.BR bs =auto
|
||||
option is used (to determine the boot file size).
|
||||
A reply may be sent whether or not the boot file exists.
|
||||
.PP
|
||||
Some newer versions of
|
||||
.I tftpd
|
||||
provide a security feature to change their root directory using
|
||||
the
|
||||
.IR chroot (2)
|
||||
system call.
|
||||
The
|
||||
.B td
|
||||
tag may be used to inform
|
||||
.I bootpd
|
||||
of this special root directory used by
|
||||
.IR tftpd .
|
||||
(One may alternatively use the
|
||||
.I bootpd
|
||||
"-c chdir" option.)
|
||||
The
|
||||
.B hd
|
||||
tag is actually relative to the root directory specified by the
|
||||
.B td
|
||||
tag.
|
||||
For example, if the real absolute path to your BOOTP client bootfile is
|
||||
/tftpboot/bootfiles/bootimage, and
|
||||
.IR tftpd
|
||||
uses /tftpboot as its "secure" directory, then specify the following in
|
||||
.IR bootptab :
|
||||
.PP
|
||||
.br
|
||||
:td=/tftpboot:hd=/bootfiles:bf=bootimage:
|
||||
.PP
|
||||
If your bootfiles are located directly in /tftpboot, use:
|
||||
.PP
|
||||
.br
|
||||
:td=/tftpboot:hd=/:bf=bootimage:
|
||||
.PP
|
||||
The
|
||||
.B sa
|
||||
tag may be used to specify the IP address of the particular TFTP server
|
||||
you wish the client to use. In the absence of this tag,
|
||||
.I bootpd
|
||||
will tell the client to perform TFTP to the same machine
|
||||
.I bootpd
|
||||
is running on.
|
||||
.PP
|
||||
The time offset
|
||||
.B to
|
||||
may be either a signed decimal integer specifying the client's
|
||||
time zone offset in seconds from UTC, or the keyword
|
||||
.B auto
|
||||
which uses the server's time zone offset. Specifying the
|
||||
.B to
|
||||
symbol as a boolean has the same effect as specifying
|
||||
.B auto
|
||||
as its value.
|
||||
.PP
|
||||
The bootfile size
|
||||
.B bs
|
||||
may be either a decimal, octal, or hexadecimal integer specifying the size of
|
||||
the bootfile in 512-octet blocks, or the keyword
|
||||
.B auto
|
||||
which causes the server to automatically calculate the bootfile size at each
|
||||
request. As with the time offset, specifying the
|
||||
.B bs
|
||||
symbol as a boolean has the same effect as specifying
|
||||
.B auto
|
||||
as its value.
|
||||
.PP
|
||||
The vendor magic cookie selector (the
|
||||
.B vm
|
||||
tag) may take one of the following keywords:
|
||||
.B auto
|
||||
(indicating that vendor information is determined by the client's request),
|
||||
.B rfc1048
|
||||
or
|
||||
.B rfc1084
|
||||
(which always forces an RFC1084-style reply), or
|
||||
.B cmu
|
||||
(which always forces a CMU-style reply).
|
||||
.PP
|
||||
The
|
||||
.B hn
|
||||
tag is strictly a boolean tag; it does not take the usual equals-sign and
|
||||
value. It's presence indicates that the hostname should be sent to RFC1084
|
||||
clients.
|
||||
.I Bootpd
|
||||
attempts to send the entire hostname as it is specified in the configuration
|
||||
file; if this will not fit into the reply packet, the name is shortened to
|
||||
just the host field (up to the first period, if present) and then tried.
|
||||
In no case is an arbitrarily-truncated hostname sent (if nothing reasonable
|
||||
will fit, nothing is sent).
|
||||
.PP
|
||||
Often, many host entries share common values for certain tags (such as name
|
||||
servers, etc.). Rather than repeatedly specifying these tags, a full
|
||||
specification can be listed for one host entry and shared by others via the
|
||||
.B tc
|
||||
(table continuation) mechanism.
|
||||
Often, the template entry is a dummy host which doesn't actually exist and
|
||||
never sends bootp requests. This feature is similar to the
|
||||
.B tc
|
||||
feature of
|
||||
.IR termcap (5)
|
||||
for similar terminals. Note that
|
||||
.I bootpd
|
||||
allows the
|
||||
.B tc
|
||||
tag symbol to appear anywhere in the host entry, unlike
|
||||
.I termcap
|
||||
which requires it to be the last tag. Information explicitly specified for a
|
||||
host always overrides information implied by a
|
||||
.B tc
|
||||
tag symbol, regardless of its location within the entry. The
|
||||
value of the
|
||||
.B tc
|
||||
tag may be the hostname or IP address of any host entry
|
||||
previously listed in the configuration file.
|
||||
.PP
|
||||
Sometimes it is necessary to delete a specific tag after it has been inferred
|
||||
via
|
||||
.BR tc .
|
||||
This can be done using the construction
|
||||
.IB tag @
|
||||
which removes the effect of
|
||||
.I tag
|
||||
as in
|
||||
.IR termcap (5).
|
||||
For example, to completely undo an IEN-116 name server specification, use
|
||||
":ns@:" at an appropriate place in the configuration entry. After removal
|
||||
with
|
||||
.BR @ ,
|
||||
a tag is eligible to be set again through the
|
||||
.B tc
|
||||
mechanism.
|
||||
.PP
|
||||
Blank lines and lines beginning with "#" are ignored in the configuration
|
||||
file. Host entries are separated from one another by newlines; a single host
|
||||
entry may be extended over multiple lines if the lines end with a backslash
|
||||
(\\). It is also acceptable for lines to be longer than 80 characters. Tags
|
||||
may appear in any order, with the following exceptions: the hostname must be
|
||||
the very first field in an entry, and the hardware type must precede the
|
||||
hardware address.
|
||||
.PP
|
||||
An example
|
||||
.I /etc/bootptab
|
||||
file follows:
|
||||
.PP
|
||||
.nf
|
||||
# Sample bootptab file (domain=andrew.cmu.edu)
|
||||
|
||||
.default:\\
|
||||
:hd=/usr/boot:bf=null:\\
|
||||
:ds=netserver, lancaster:\\
|
||||
:ns=pcs2, pcs1:\\
|
||||
:ts=pcs2, pcs1:\\
|
||||
:sm=255.255.255.0:\\
|
||||
:gw=gw.cs.cmu.edu:\\
|
||||
:hn:to=-18000:
|
||||
|
||||
carnegie:ht=6:ha=7FF8100000AF:tc=.default:
|
||||
baldwin:ht=1:ha=0800200159C3:tc=.default:
|
||||
wylie:ht=1:ha=00DD00CADF00:tc=.default:
|
||||
arnold:ht=1:ha=0800200102AD:tc=.default:
|
||||
bairdford:ht=1:ha=08002B02A2F9:tc=.default:
|
||||
bakerstown:ht=1:ha=08002B0287C8:tc=.default:
|
||||
|
||||
# Special domain name server and option tags for next host
|
||||
butlerjct:ha=08002001560D:ds=128.2.13.42:\\
|
||||
:T37=0x12345927AD3BCF:\\
|
||||
:T99="Special ASCII string":\\
|
||||
:tc=.default:
|
||||
|
||||
gastonville:ht=6:ha=7FFF81000A47:tc=.default:
|
||||
hahntown:ht=6:ha=7FFF81000434:tc=.default:
|
||||
hickman:ht=6:ha=7FFF810001BA:tc=.default:
|
||||
lowber:ht=1:ha=00DD00CAF000:tc=.default:
|
||||
mtoliver:ht=1:ha=00DD00FE1600:tc=.default:
|
||||
|
||||
.fi
|
||||
.SH FILES
|
||||
/etc/bootptab
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.br
|
||||
bootpd(8), tftpd(8),
|
||||
.br
|
||||
DARPA Internet Request For Comments RFC951, RFC1048, RFC1084, Assigned Numbers
|
124
libexec/bootpd/bootptab.cmu
Normal file
124
libexec/bootpd/bootptab.cmu
Normal file
@ -0,0 +1,124 @@
|
||||
# /etc/bootptab: database for bootp server (/etc/bootpd)
|
||||
# (I've hacked on this but can't test it... -gwr)
|
||||
|
||||
# Blank lines and lines beginning with '#' are ignored.
|
||||
#
|
||||
# Legend: (see bootptab.5)
|
||||
# first field -- hostname (not indented)
|
||||
# bf -- bootfile
|
||||
# bs -- bootfile size in 512-octet blocks
|
||||
# cs -- cookie servers
|
||||
# df -- dump file name
|
||||
# dn -- domain name
|
||||
# ds -- domain name servers
|
||||
# ef -- extension file
|
||||
# gw -- gateways
|
||||
# ha -- hardware address
|
||||
# hd -- home directory for bootfiles
|
||||
# hn -- host name set for client
|
||||
# ht -- hardware type
|
||||
# im -- impress servers
|
||||
# ip -- host IP address
|
||||
# lg -- log servers
|
||||
# lp -- LPR servers
|
||||
# ns -- IEN-116 name servers
|
||||
# ra -- reply address
|
||||
# rl -- resource location protocol servers
|
||||
# rp -- root path
|
||||
# sa -- boot server address
|
||||
# sm -- subnet mask
|
||||
# sw -- swap server
|
||||
# tc -- template host (points to similar host entry)
|
||||
# td -- TFTP directory
|
||||
# to -- time offset (seconds)
|
||||
# ts -- time servers
|
||||
# vm -- vendor magic number
|
||||
# Tn -- generic option tag n
|
||||
#
|
||||
# Be careful about including backslashes where they're needed. Weird (bad)
|
||||
# things can happen when a backslash is omitted where one is intended.
|
||||
# Also, note that generic option data must be either a string or a
|
||||
# sequence of bytes where each byte is a two-digit hex value.
|
||||
|
||||
# First, we define a global entry which specifies the stuff every host uses.
|
||||
# (Host name lookups are relative to the domain: andrew.cmu.edu)
|
||||
.default:\
|
||||
:hn:dn=cmu.edu:\
|
||||
:hd=/usr/boot:\
|
||||
:ds=netserver, lancaster:\
|
||||
:ns=pcs2, pcs1:\
|
||||
:ts=pcs2, pcs1:\
|
||||
:sm=255.255.0.0:\
|
||||
:gw=gw.cs.cmu.edu:\
|
||||
to=auto:
|
||||
|
||||
|
||||
# Next, we can define different master entries for each subnet. . .
|
||||
.subnet13 :sm=255.255.255.0:gw=128.2.13.1 :tc=.default:
|
||||
.subnet19 :sm=255.255.255.0:gw=128.2.19.1 :tc=.default:
|
||||
.subnet232 :sm=255.255.255.0:gw=128.2.232.1 :tc=.default:
|
||||
|
||||
#
|
||||
# We should be able to use as many levels of indirection as desired. Use
|
||||
# your imagination. . .
|
||||
#
|
||||
|
||||
|
||||
# Individual entries (could also have different servers for some/all of these
|
||||
# hosts, but we don't really use this feature at CMU):
|
||||
|
||||
carnegie:tc=.subnet13:ht=ieee802:ha=7FF8100000AF:
|
||||
baldwin:tc=.subnet19:ha=0800200159C3:
|
||||
wylie:tc=.subnet232:ha=00DD00CADF00:
|
||||
arnold:tc=.subnet19:ha=0800200102AD:
|
||||
bairdford:tc=.subnet19:ha=08002B02A2F9:
|
||||
bakerstown:tc=.subnet19:ha=08002B0287C8:
|
||||
butlerjct:tc=.subnet232:ha=08002001560D:
|
||||
gastonville:tc=.subnet232:ht=ieee802:ha=7FFF81000A47:
|
||||
hahntown:tc=.subnet13:ht=ieee802:ha=7FFF81000434:
|
||||
hickman:tc=.subnet19:ht=ieee802:ha=7FFF810001BA:
|
||||
lowber:tc=.subnet13:ha=00DD00CAF000:
|
||||
mtoliver:tc=.subnet19:ha=00DD00FE1600:
|
||||
osborne:tc=.subnet232:ha=00DD00CAD600:
|
||||
russelton:tc=.subnet232:ha=080020017FC3:
|
||||
thornburg:tc=.subnet13:ha=080020012A33:
|
||||
|
||||
|
||||
# Hmmm. . . Let's throw in some whitespace for readability. . . .
|
||||
|
||||
andrew: tc=.subnet19:ha=00DD00C88900:
|
||||
birdville: tc=.subnet19:ha=00DD00FE2D00:
|
||||
coudersport: tc=.subnet13:ha=00DD00CB1E00:
|
||||
bridgeville: tc=.subnet232:ha=080020011394:
|
||||
franklin: tc=.subnet19:ha=08002B02A5D5:
|
||||
hollidaysburg: tc=.subnet19:ht=ieee802:ha=7FFF810002C8:
|
||||
honesdale: tc=.subnet19:ha=08002B02F83F:
|
||||
huntingdon: tc=.subnet19:ha=08002B02E410:
|
||||
indiana: tc=.subnet13:ha=08002B029BEC:
|
||||
jimthorpe: tc=.subnet232:ha=08002B02FBBA:
|
||||
kittanning: tc=.subnet232:ha=08002B0273FC:
|
||||
lebanon: tc=.subnet232:ha=08002B037F67:
|
||||
lewisburg: tc=.subnet19:ha=50005A1A0DE4:
|
||||
middleburg: tc=.subnet232:ha=00DD00FE1200:
|
||||
aspinwall: tc=.subnet13:ha=08002B03C163:
|
||||
berlin: tc=.subnet13:ha=00DD000A4400:
|
||||
norristown: tc=.subnet13:ha=08002001455B:
|
||||
pottsville: tc=.subnet13:ha=00DD000A3700:
|
||||
ridgway: tc=.subnet19:ha=08002B029425:
|
||||
scranton: tc=.subnet232:ha=0800200113A1:
|
||||
chalfont: tc=.subnet13:ha=08002001124B:
|
||||
washington: tc=.subnet19:ha=00DD00656E00:
|
||||
wellsboro: tc=.subnet13:ha=00DD00CB1C00:
|
||||
bb1: tc=.subnet19:ha=00DD000A1F00:
|
||||
adamstown: tc=.subnet13:ha=08002B02D0E6:
|
||||
beta: tc=.subnet19:ha=02070100B197:
|
||||
carbondale: tc=.subnet232:ha=08002B022A73:
|
||||
clairton: tc=.subnet19:ha=080020010FD1:
|
||||
egypt: tc=.subnet13:ha=00DD00847B00:
|
||||
fairchance: tc=.subnet232:ha=00DD000AB100:
|
||||
fairhope: tc=.subnet232:ha=00DD00CB0800:
|
||||
galeton: tc=.subnet232:ha=08002001138C:
|
||||
imperial: tc=.subnet232:ha=08002001130C:
|
||||
kingston: tc=.subnet232:ha=080020011382:
|
||||
knox: tc=.subnet232:ha=50005A1A0D2A:
|
||||
lakecity: tc=.subnet13:ha=080020011380:
|
92
libexec/bootpd/bootptab.mcs
Normal file
92
libexec/bootpd/bootptab.mcs
Normal file
@ -0,0 +1,92 @@
|
||||
# /etc/bootptab: database for bootp server (/etc/bootpd)
|
||||
# Last update: gwr, Sun Dec 12 19:00:00 EDT 1993
|
||||
# Blank lines and lines beginning with '#' are ignored.
|
||||
#
|
||||
# Legend: (see bootptab.5)
|
||||
# first field -- hostname (not indented)
|
||||
# bf -- bootfile
|
||||
# bs -- bootfile size in 512-octet blocks
|
||||
# cs -- cookie servers
|
||||
# df -- dump file name
|
||||
# dn -- domain name
|
||||
# ds -- domain name servers
|
||||
# ef -- extension file
|
||||
# gw -- gateways
|
||||
# ha -- hardware address
|
||||
# hd -- home directory for bootfiles
|
||||
# hn -- host name set for client
|
||||
# ht -- hardware type
|
||||
# im -- impress servers
|
||||
# ip -- host IP address
|
||||
# lg -- log servers
|
||||
# lp -- LPR servers
|
||||
# ns -- IEN-116 name servers
|
||||
# ra -- reply address
|
||||
# rl -- resource location protocol servers
|
||||
# rp -- root path
|
||||
# sa -- boot server address
|
||||
# sm -- subnet mask
|
||||
# sw -- swap server
|
||||
# tc -- template host (points to similar host entry)
|
||||
# td -- TFTP directory
|
||||
# to -- time offset (seconds)
|
||||
# ts -- time servers
|
||||
# vm -- vendor magic number
|
||||
# Tn -- generic option tag n
|
||||
#
|
||||
# Be careful about including backslashes where they're needed. Weird (bad)
|
||||
# things can happen when a backslash is omitted where one is intended.
|
||||
# Also, note that generic option data must be either a string or a
|
||||
# sequence of bytes where each byte is a two-digit hex value.
|
||||
|
||||
# First, we define a global entry which specifies the stuff every host uses.
|
||||
|
||||
# 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:\
|
||||
:ds=merlin, jericho:\
|
||||
:to=auto:
|
||||
|
||||
# Next, we can define different master entries for each subnet. . .
|
||||
|
||||
.subnet16:\
|
||||
:tc=.default:\
|
||||
:sm=255.255.255.0:\
|
||||
:gw=merlin:\
|
||||
:sa=merlin:
|
||||
|
||||
.subnet17:\
|
||||
:tc=.default:\
|
||||
:sm=255.255.255.0:\
|
||||
:gw=merlin-gw:\
|
||||
:sa=merlin-gw:
|
||||
|
||||
#
|
||||
# We should be able to use as many levels of indirection as desired. Use
|
||||
# your imagination. . .
|
||||
#
|
||||
|
||||
# Individual entries (could also have different servers for some/all of these
|
||||
# hosts, but we don't really use this feature at CMU):
|
||||
|
||||
# Emulex terminal server
|
||||
emulex: tc=.subnet16:ha=00.00.C9.00.42.E0:bf=P4KTL0E:
|
||||
|
||||
# Lantronix eps1
|
||||
eps1: tc=.subnet16:ha=00.80.A3.04.1D.78:
|
||||
|
||||
# Tadpole 885 board.
|
||||
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:
|
||||
|
||||
# These are just for testing
|
||||
|
||||
walnut:tc=.subnet16:ha=walnut:
|
||||
banana:tc=.subnet17:ha=banana:
|
||||
thor:tc=.subnet17:ha=thor:
|
||||
classic:tc=.subnet16:ha=classic:
|
23
libexec/bootpd/bptypes.h
Normal file
23
libexec/bootpd/bptypes.h
Normal file
@ -0,0 +1,23 @@
|
||||
/* bptypes.h */
|
||||
|
||||
#ifndef BPTYPES_H
|
||||
#define BPTYPES_H
|
||||
|
||||
/*
|
||||
* 32 bit integers are different types on various architectures
|
||||
*/
|
||||
|
||||
#ifndef int32
|
||||
#define int32 long
|
||||
#endif
|
||||
typedef unsigned int32 u_int32;
|
||||
|
||||
/*
|
||||
* Nice typedefs. . .
|
||||
*/
|
||||
|
||||
typedef int boolean;
|
||||
typedef unsigned char byte;
|
||||
|
||||
|
||||
#endif /* BPTYPES_H */
|
413
libexec/bootpd/dovend.c
Normal file
413
libexec/bootpd/dovend.c
Normal file
@ -0,0 +1,413 @@
|
||||
/*
|
||||
* dovend.c : Inserts all but the first few vendor options.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h> /* inet_ntoa */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#ifndef USE_BFUNCS
|
||||
# include <memory.h>
|
||||
/* Yes, memcpy is OK here (no overlapped copies). */
|
||||
# define bcopy(a,b,c) memcpy(b,a,c)
|
||||
# define bzero(p,l) memset(p,0,l)
|
||||
# define bcmp(a,b,c) memcmp(a,b,c)
|
||||
# define index strchr
|
||||
#endif
|
||||
|
||||
#include "bootp.h"
|
||||
#include "bootpd.h"
|
||||
#include "report.h"
|
||||
#include "dovend.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
#define P(args) args
|
||||
#else
|
||||
#define P(args) ()
|
||||
#endif
|
||||
|
||||
PRIVATE int insert_generic P((struct shared_bindata *, byte **, int *));
|
||||
|
||||
/*
|
||||
* Insert the 2nd part of the options into an option buffer.
|
||||
* Return amount of space used.
|
||||
*
|
||||
* This inserts everything EXCEPT:
|
||||
* magic cookie, subnet mask, gateway, bootsize, extension file
|
||||
* Those are handled separately (in bootpd.c) to allow this function
|
||||
* to be shared between bootpd and bootpef.
|
||||
*
|
||||
* When an "extension file" is in use, the options inserted by
|
||||
* this function go into the exten_file, not the bootp response.
|
||||
*/
|
||||
|
||||
int
|
||||
dovend_rfc1497(hp, buf, len)
|
||||
struct host *hp;
|
||||
byte *buf;
|
||||
int len;
|
||||
{
|
||||
int bytesleft = len;
|
||||
byte *vp = buf;
|
||||
char *tmpstr;
|
||||
|
||||
static char noroom[] = "%s: No room for \"%s\" option";
|
||||
#define NEED(LEN, MSG) do \
|
||||
if (bytesleft < (LEN)) { \
|
||||
report(LOG_NOTICE, noroom, \
|
||||
hp->hostname->string, MSG); \
|
||||
return (vp - buf); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Note that the following have already been inserted:
|
||||
* magic_cookie, subnet_mask, gateway, bootsize
|
||||
*
|
||||
* The remaining options are inserted in order of importance.
|
||||
* (Of course the importance of each is a matter of opinion.)
|
||||
* The option insertion order should probably be configurable.
|
||||
*
|
||||
* This is the order used in the NetBSD version. Can anyone
|
||||
* explain why the time_offset and swap_server are first?
|
||||
* Also, why is the hostname so far down the list? -gwr
|
||||
*/
|
||||
|
||||
if (hp->flags.time_offset) {
|
||||
NEED(6, "to");
|
||||
*vp++ = TAG_TIME_OFFSET;/* -1 byte */
|
||||
*vp++ = 4; /* -1 byte */
|
||||
insert_u_long(htonl(hp->time_offset), &vp); /* -4 bytes */
|
||||
bytesleft -= 6;
|
||||
}
|
||||
/*
|
||||
* swap server, root path, dump path
|
||||
*/
|
||||
if (hp->flags.swap_server) {
|
||||
NEED(6, "sw");
|
||||
/* There is just one SWAP_SERVER, so it is not an iplist. */
|
||||
*vp++ = TAG_SWAP_SERVER;/* -1 byte */
|
||||
*vp++ = 4; /* -1 byte */
|
||||
insert_u_long(hp->swap_server.s_addr, &vp); /* -4 bytes */
|
||||
bytesleft -= 6; /* Fix real count */
|
||||
}
|
||||
if (hp->flags.root_path) {
|
||||
/*
|
||||
* Check for room for root_path. Add 2 to account for
|
||||
* TAG_ROOT_PATH and length.
|
||||
*/
|
||||
len = strlen(hp->root_path->string);
|
||||
NEED((len + 2), "rp");
|
||||
*vp++ = TAG_ROOT_PATH;
|
||||
*vp++ = (byte) (len & 0xFF);
|
||||
bcopy(hp->root_path->string, vp, len);
|
||||
vp += len;
|
||||
bytesleft -= len + 2;
|
||||
}
|
||||
if (hp->flags.dump_file) {
|
||||
/*
|
||||
* Check for room for dump_file. Add 2 to account for
|
||||
* TAG_DUMP_FILE and length.
|
||||
*/
|
||||
len = strlen(hp->dump_file->string);
|
||||
NEED((len + 2), "df");
|
||||
*vp++ = TAG_DUMP_FILE;
|
||||
*vp++ = (byte) (len & 0xFF);
|
||||
bcopy(hp->dump_file->string, vp, len);
|
||||
vp += len;
|
||||
bytesleft -= len + 2;
|
||||
}
|
||||
/*
|
||||
* DNS server and domain
|
||||
*/
|
||||
if (hp->flags.domain_server) {
|
||||
if (insert_ip(TAG_DOMAIN_SERVER,
|
||||
hp->domain_server,
|
||||
&vp, &bytesleft))
|
||||
NEED(8, "ds");
|
||||
}
|
||||
if (hp->flags.domain_name) {
|
||||
/*
|
||||
* Check for room for domain_name. Add 2 to account for
|
||||
* TAG_DOMAIN_NAME and length.
|
||||
*/
|
||||
len = strlen(hp->domain_name->string);
|
||||
NEED((len + 2), "dn");
|
||||
*vp++ = TAG_DOMAIN_NAME;
|
||||
*vp++ = (byte) (len & 0xFF);
|
||||
bcopy(hp->domain_name->string, vp, len);
|
||||
vp += len;
|
||||
bytesleft -= len + 2;
|
||||
}
|
||||
/*
|
||||
* NIS (YP) server and domain
|
||||
*/
|
||||
if (hp->flags.nis_server) {
|
||||
if (insert_ip(TAG_NIS_SERVER,
|
||||
hp->nis_server,
|
||||
&vp, &bytesleft))
|
||||
NEED(8, "ds");
|
||||
}
|
||||
if (hp->flags.nis_domain) {
|
||||
/*
|
||||
* Check for room for nis_domain. Add 2 to account for
|
||||
* TAG_NIS_DOMAIN and length.
|
||||
*/
|
||||
len = strlen(hp->nis_domain->string);
|
||||
NEED((len + 2), "dn");
|
||||
*vp++ = TAG_NIS_DOMAIN;
|
||||
*vp++ = (byte) (len & 0xFF);
|
||||
bcopy(hp->nis_domain->string, vp, len);
|
||||
vp += len;
|
||||
bytesleft -= len + 2;
|
||||
}
|
||||
/* IEN 116 name server */
|
||||
if (hp->flags.name_server) {
|
||||
if (insert_ip(TAG_NAME_SERVER,
|
||||
hp->name_server,
|
||||
&vp, &bytesleft))
|
||||
NEED(8, "ns");
|
||||
}
|
||||
if (hp->flags.rlp_server) {
|
||||
if (insert_ip(TAG_RLP_SERVER,
|
||||
hp->rlp_server,
|
||||
&vp, &bytesleft))
|
||||
NEED(8, "rl");
|
||||
}
|
||||
/* Time server (RFC 868) */
|
||||
if (hp->flags.time_server) {
|
||||
if (insert_ip(TAG_TIME_SERVER,
|
||||
hp->time_server,
|
||||
&vp, &bytesleft))
|
||||
NEED(8, "ts");
|
||||
}
|
||||
/* NTP (time) Server (RFC 1129) */
|
||||
if (hp->flags.ntp_server) {
|
||||
if (insert_ip(TAG_NTP_SERVER,
|
||||
hp->ntp_server,
|
||||
&vp, &bytesleft))
|
||||
NEED(8, "ts");
|
||||
}
|
||||
/*
|
||||
* I wonder: If the hostname were "promoted" into the BOOTP
|
||||
* response part, might these "extension" files possibly be
|
||||
* shared between several clients?
|
||||
*
|
||||
* Also, why not just use longer BOOTP packets with all the
|
||||
* additional length used as option data. This bootpd version
|
||||
* already supports that feature by replying with the same
|
||||
* packet length as the client request packet. -gwr
|
||||
*/
|
||||
if (hp->flags.name_switch && hp->flags.send_name) {
|
||||
/*
|
||||
* Check for room for hostname. Add 2 to account for
|
||||
* TAG_HOST_NAME and length.
|
||||
*/
|
||||
len = strlen(hp->hostname->string);
|
||||
#if 0
|
||||
/*
|
||||
* XXX - Too much magic. The user can always set the hostname
|
||||
* to the short version in the bootptab file. -gwr
|
||||
*/
|
||||
if ((len + 2) > bytesleft) {
|
||||
/*
|
||||
* Not enough room for full (domain-qualified) hostname, try
|
||||
* stripping it down to just the first field (host).
|
||||
*/
|
||||
tmpstr = hp->hostname->string;
|
||||
len = 0;
|
||||
while (*tmpstr && (*tmpstr != '.')) {
|
||||
tmpstr++;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
NEED((len + 2), "hn");
|
||||
*vp++ = TAG_HOST_NAME;
|
||||
*vp++ = (byte) (len & 0xFF);
|
||||
bcopy(hp->hostname->string, vp, len);
|
||||
vp += len;
|
||||
bytesleft -= len + 2;
|
||||
}
|
||||
/*
|
||||
* The rest of these are less important, so they go last.
|
||||
*/
|
||||
if (hp->flags.lpr_server) {
|
||||
if (insert_ip(TAG_LPR_SERVER,
|
||||
hp->lpr_server,
|
||||
&vp, &bytesleft))
|
||||
NEED(8, "lp");
|
||||
}
|
||||
if (hp->flags.cookie_server) {
|
||||
if (insert_ip(TAG_COOKIE_SERVER,
|
||||
hp->cookie_server,
|
||||
&vp, &bytesleft))
|
||||
NEED(8, "cs");
|
||||
}
|
||||
if (hp->flags.log_server) {
|
||||
if (insert_ip(TAG_LOG_SERVER,
|
||||
hp->log_server,
|
||||
&vp, &bytesleft))
|
||||
NEED(8, "lg");
|
||||
}
|
||||
/*
|
||||
* XXX - Add new tags here (to insert options)
|
||||
*/
|
||||
if (hp->flags.generic) {
|
||||
if (insert_generic(hp->generic, &vp, &bytesleft))
|
||||
NEED(64, "(generic)");
|
||||
}
|
||||
/*
|
||||
* The end marker is inserted by the caller.
|
||||
*/
|
||||
return (vp - buf);
|
||||
#undef NEED
|
||||
} /* dovend_rfc1497 */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Insert a tag value, a length value, and a list of IP addresses into the
|
||||
* memory buffer indirectly pointed to by "dest". "tag" is the RFC1048 tag
|
||||
* number to use, "iplist" is a pointer to a list of IP addresses
|
||||
* (struct in_addr_list), and "bytesleft" points to an integer which
|
||||
* indicates the size of the "dest" buffer.
|
||||
*
|
||||
* Return zero if everything fits.
|
||||
*
|
||||
* This is used to fill the vendor-specific area of a bootp packet in
|
||||
* conformance to RFC1048.
|
||||
*/
|
||||
|
||||
int
|
||||
insert_ip(tag, iplist, dest, bytesleft)
|
||||
byte tag;
|
||||
struct in_addr_list *iplist;
|
||||
byte **dest;
|
||||
int *bytesleft;
|
||||
{
|
||||
struct in_addr *addrptr;
|
||||
unsigned addrcount = 1;
|
||||
byte *d;
|
||||
|
||||
if (iplist == NULL)
|
||||
return (0);
|
||||
|
||||
if (*bytesleft >= 6) {
|
||||
d = *dest; /* Save pointer for later */
|
||||
**dest = tag;
|
||||
(*dest) += 2;
|
||||
(*bytesleft) -= 2; /* Account for tag and length */
|
||||
addrptr = iplist->addr;
|
||||
addrcount = iplist->addrcount;
|
||||
while ((*bytesleft >= 4) && (addrcount > 0)) {
|
||||
insert_u_long(addrptr->s_addr, dest);
|
||||
addrptr++;
|
||||
addrcount--;
|
||||
(*bytesleft) -= 4; /* Four bytes per address */
|
||||
}
|
||||
d[1] = (byte) ((*dest - d - 2) & 0xFF);
|
||||
}
|
||||
return (addrcount);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Insert generic data into a bootp packet. The data is assumed to already
|
||||
* be in RFC1048 format. It is inserted using a first-fit algorithm which
|
||||
* attempts to insert as many tags as possible. Tags and data which are
|
||||
* too large to fit are skipped; any remaining tags are tried until they
|
||||
* have all been exhausted.
|
||||
* Return zero if everything fits.
|
||||
*/
|
||||
|
||||
static int
|
||||
insert_generic(gendata, buff, bytesleft)
|
||||
struct shared_bindata *gendata;
|
||||
byte **buff;
|
||||
int *bytesleft;
|
||||
{
|
||||
byte *srcptr;
|
||||
int length, numbytes;
|
||||
int skipped = 0;
|
||||
|
||||
if (gendata == NULL)
|
||||
return (0);
|
||||
|
||||
srcptr = gendata->data;
|
||||
length = gendata->length;
|
||||
while ((length > 0) && (*bytesleft > 0)) {
|
||||
switch (*srcptr) {
|
||||
case TAG_END:
|
||||
length = 0; /* Force an exit on next iteration */
|
||||
break;
|
||||
case TAG_PAD:
|
||||
*(*buff)++ = *srcptr++;
|
||||
(*bytesleft)--;
|
||||
length--;
|
||||
break;
|
||||
default:
|
||||
numbytes = srcptr[1] + 2;
|
||||
if (*bytesleft < numbytes)
|
||||
skipped += numbytes;
|
||||
else {
|
||||
bcopy(srcptr, *buff, numbytes);
|
||||
(*buff) += numbytes;
|
||||
(*bytesleft) -= numbytes;
|
||||
}
|
||||
srcptr += numbytes;
|
||||
length -= numbytes;
|
||||
break;
|
||||
}
|
||||
} /* while */
|
||||
return (skipped);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert the unsigned long "value" into memory starting at the byte
|
||||
* pointed to by the byte pointer (*dest). (*dest) is updated to
|
||||
* point to the next available byte.
|
||||
*
|
||||
* Since it is desirable to internally store network addresses in network
|
||||
* byte order (in struct in_addr's), this routine expects longs to be
|
||||
* passed in network byte order.
|
||||
*
|
||||
* However, due to the nature of the main algorithm, the long must be in
|
||||
* host byte order, thus necessitating the use of ntohl() first.
|
||||
*/
|
||||
|
||||
void
|
||||
insert_u_long(value, dest)
|
||||
u_int32 value;
|
||||
byte **dest;
|
||||
{
|
||||
byte *temp;
|
||||
int n;
|
||||
|
||||
value = ntohl(value); /* Must use host byte order here */
|
||||
temp = (*dest += 4);
|
||||
for (n = 4; n > 0; n--) {
|
||||
*--temp = (byte) (value & 0xFF);
|
||||
value >>= 8;
|
||||
}
|
||||
/* Final result is network byte order */
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-argdecl-indent: 4
|
||||
* c-continued-statement-offset: 4
|
||||
* c-continued-brace-offset: -4
|
||||
* c-label-offset: -4
|
||||
* c-brace-offset: 0
|
||||
* End:
|
||||
*/
|
13
libexec/bootpd/dovend.h
Normal file
13
libexec/bootpd/dovend.h
Normal file
@ -0,0 +1,13 @@
|
||||
/* dovend.h */
|
||||
|
||||
#ifdef __STDC__
|
||||
#define P(args) args
|
||||
#else
|
||||
#define P(args) ()
|
||||
#endif
|
||||
|
||||
extern int dovend_rfc1497 P((struct host *hp, u_char *buf, int len));
|
||||
extern int insert_ip P((int, struct in_addr_list *, u_char **, int *));
|
||||
extern void insert_u_long P((u_int32, u_char **));
|
||||
|
||||
#undef P
|
382
libexec/bootpd/dumptab.c
Normal file
382
libexec/bootpd/dumptab.c
Normal file
@ -0,0 +1,382 @@
|
||||
/*
|
||||
* dumptab.c - handles dumping the database
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h> /* inet_ntoa */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifndef USE_BFUNCS
|
||||
#include <memory.h>
|
||||
/* Yes, memcpy is OK here (no overlapped copies). */
|
||||
#define bcopy(a,b,c) memcpy(b,a,c)
|
||||
#define bzero(p,l) memset(p,0,l)
|
||||
#define bcmp(a,b,c) memcmp(a,b,c)
|
||||
#endif
|
||||
|
||||
#include "bootp.h"
|
||||
#include "hash.h"
|
||||
#include "hwaddr.h"
|
||||
#include "report.h"
|
||||
#include "patchlevel.h"
|
||||
#include "bootpd.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
#define P(args) args
|
||||
#else
|
||||
#define P(args) ()
|
||||
#endif
|
||||
|
||||
static void dump_generic P((FILE *, struct shared_bindata *));
|
||||
static void dump_host P((FILE *, struct host *));
|
||||
static void list_ipaddresses P((FILE *, struct in_addr_list *));
|
||||
|
||||
#undef P
|
||||
|
||||
#ifndef DEBUG
|
||||
void
|
||||
dumptab(filename)
|
||||
char *filename;
|
||||
{
|
||||
report(LOG_INFO, "No dumptab support!");
|
||||
}
|
||||
|
||||
#else /* DEBUG */
|
||||
|
||||
/*
|
||||
* Dump the internal memory database to bootpd_dump.
|
||||
*/
|
||||
|
||||
void
|
||||
dumptab(filename)
|
||||
char *filename;
|
||||
{
|
||||
int n;
|
||||
struct host *hp;
|
||||
FILE *fp;
|
||||
long t;
|
||||
/* Print symbols in alphabetical order for reader's convenience. */
|
||||
static char legend[] = "#\n# Legend:\t(see bootptab.5)\n\
|
||||
#\tfirst field -- hostname (not indented)\n\
|
||||
#\tbf -- bootfile\n\
|
||||
#\tbs -- bootfile size in 512-octet blocks\n\
|
||||
#\tcs -- cookie servers\n\
|
||||
#\tdf -- dump file name\n\
|
||||
#\tdn -- domain name\n\
|
||||
#\tds -- domain name servers\n\
|
||||
#\tef -- extension file\n\
|
||||
#\tex -- exec file (YORK_EX_OPTION)\n\
|
||||
#\tgw -- gateways\n\
|
||||
#\tha -- hardware address\n\
|
||||
#\thd -- home directory for bootfiles\n\
|
||||
#\thn -- host name set for client\n\
|
||||
#\tht -- hardware type\n\
|
||||
#\tim -- impress servers\n\
|
||||
#\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\
|
||||
#\trl -- resource location protocol servers\n\
|
||||
#\trp -- root path\n\
|
||||
#\tsa -- boot server address\n\
|
||||
#\tsm -- subnet mask\n\
|
||||
#\tsw -- swap server\n\
|
||||
#\ttc -- template host (points to similar host entry)\n\
|
||||
#\ttd -- TFTP directory\n\
|
||||
#\tto -- time offset (seconds)\n\
|
||||
#\tts -- time servers\n\
|
||||
#\tvm -- vendor magic number\n\
|
||||
#\tyd -- YP (NIS) domain\n\
|
||||
#\tys -- YP (NIS) servers\n\
|
||||
#\tTn -- generic option tag n\n\
|
||||
\n";
|
||||
|
||||
/*
|
||||
* Open bootpd.dump file.
|
||||
*/
|
||||
if ((fp = fopen(filename, "w")) == NULL) {
|
||||
report(LOG_ERR, "error opening \"%s\": %s",
|
||||
filename, get_errmsg());
|
||||
exit(1);
|
||||
}
|
||||
t = time(NULL);
|
||||
fprintf(fp, "\n# %s %s.%d\n", progname, VERSION, PATCHLEVEL);
|
||||
fprintf(fp, "# %s: dump of bootp server database.\n", filename);
|
||||
fprintf(fp, "# Dump taken %s", ctime(&t));
|
||||
fwrite(legend, 1, sizeof(legend) - 1, fp);
|
||||
|
||||
n = 0;
|
||||
for (hp = (struct host *) hash_FirstEntry(nmhashtable); hp != NULL;
|
||||
hp = (struct host *) hash_NextEntry(nmhashtable)) {
|
||||
dump_host(fp, hp);
|
||||
fprintf(fp, "\n");
|
||||
n++;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
report(LOG_INFO, "dumped %d entries to \"%s\".", n, filename);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Dump all the available information on the host pointed to by "hp".
|
||||
* The output is sent to the file pointed to by "fp".
|
||||
*/
|
||||
|
||||
static void
|
||||
dump_host(fp, hp)
|
||||
FILE *fp;
|
||||
struct host *hp;
|
||||
{
|
||||
/* Print symbols in alphabetical order for reader's convenience. */
|
||||
if (hp) {
|
||||
fprintf(fp, "%s:", (hp->hostname ?
|
||||
hp->hostname->string : "?"));
|
||||
if (hp->flags.bootfile) {
|
||||
fprintf(fp, "\\\n\t:bf=%s:", hp->bootfile->string);
|
||||
}
|
||||
if (hp->flags.bootsize) {
|
||||
fprintf(fp, "\\\n\t:bs=");
|
||||
if (hp->flags.bootsize_auto) {
|
||||
fprintf(fp, "auto:");
|
||||
} else {
|
||||
fprintf(fp, "%d:", hp->bootsize);
|
||||
}
|
||||
}
|
||||
if (hp->flags.cookie_server) {
|
||||
fprintf(fp, "\\\n\t:cs=");
|
||||
list_ipaddresses(fp, hp->cookie_server);
|
||||
fprintf(fp, ":");
|
||||
}
|
||||
if (hp->flags.dump_file) {
|
||||
fprintf(fp, "\\\n\t:df=%s:", hp->dump_file->string);
|
||||
}
|
||||
if (hp->flags.domain_name) {
|
||||
fprintf(fp, "\\\n\t:dn=%s:", hp->domain_name->string);
|
||||
}
|
||||
if (hp->flags.domain_server) {
|
||||
fprintf(fp, "\\\n\t:ds=");
|
||||
list_ipaddresses(fp, hp->domain_server);
|
||||
fprintf(fp, ":");
|
||||
}
|
||||
if (hp->flags.exten_file) {
|
||||
fprintf(fp, "\\\n\t:ef=%s:", hp->exten_file->string);
|
||||
}
|
||||
if (hp->flags.exec_file) {
|
||||
fprintf(fp, "\\\n\t:ex=%s:", hp->exec_file->string);
|
||||
}
|
||||
if (hp->flags.gateway) {
|
||||
fprintf(fp, "\\\n\t:gw=");
|
||||
list_ipaddresses(fp, hp->gateway);
|
||||
fprintf(fp, ":");
|
||||
}
|
||||
/* FdC: swap_server (see below) */
|
||||
if (hp->flags.homedir) {
|
||||
fprintf(fp, "\\\n\t:hd=%s:", hp->homedir->string);
|
||||
}
|
||||
/* FdC: dump_file (see above) */
|
||||
/* FdC: domain_name (see above) */
|
||||
/* FdC: root_path (see below) */
|
||||
if (hp->flags.name_switch && hp->flags.send_name) {
|
||||
fprintf(fp, "\\\n\t:hn:");
|
||||
}
|
||||
if (hp->flags.htype) {
|
||||
int hlen = haddrlength(hp->htype);
|
||||
fprintf(fp, "\\\n\t:ht=%u:", (unsigned) hp->htype);
|
||||
if (hp->flags.haddr) {
|
||||
fprintf(fp, "ha=\"%s\":",
|
||||
haddrtoa(hp->haddr, hlen));
|
||||
}
|
||||
}
|
||||
if (hp->flags.impress_server) {
|
||||
fprintf(fp, "\\\n\t:im=");
|
||||
list_ipaddresses(fp, hp->impress_server);
|
||||
fprintf(fp, ":");
|
||||
}
|
||||
/* NetBSD: swap_server (see below) */
|
||||
if (hp->flags.iaddr) {
|
||||
fprintf(fp, "\\\n\t:ip=%s:", inet_ntoa(hp->iaddr));
|
||||
}
|
||||
if (hp->flags.log_server) {
|
||||
fprintf(fp, "\\\n\t:lg=");
|
||||
list_ipaddresses(fp, hp->log_server);
|
||||
fprintf(fp, ":");
|
||||
}
|
||||
if (hp->flags.lpr_server) {
|
||||
fprintf(fp, "\\\n\t:lp=");
|
||||
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);
|
||||
fprintf(fp, ":");
|
||||
}
|
||||
if (hp->flags.ntp_server) {
|
||||
fprintf(fp, "\\\n\t:nt=");
|
||||
list_ipaddresses(fp, hp->ntp_server);
|
||||
fprintf(fp, ":");
|
||||
}
|
||||
if (hp->flags.reply_addr) {
|
||||
fprintf(fp, "\\\n\t:ra=%s:", inet_ntoa(hp->reply_addr));
|
||||
}
|
||||
if (hp->flags.rlp_server) {
|
||||
fprintf(fp, "\\\n\t:rl=");
|
||||
list_ipaddresses(fp, hp->rlp_server);
|
||||
fprintf(fp, ":");
|
||||
}
|
||||
if (hp->flags.root_path) {
|
||||
fprintf(fp, "\\\n\t:rp=%s:", hp->root_path->string);
|
||||
}
|
||||
if (hp->flags.bootserver) {
|
||||
fprintf(fp, "\\\n\t:sa=%s:", inet_ntoa(hp->bootserver));
|
||||
}
|
||||
if (hp->flags.subnet_mask) {
|
||||
fprintf(fp, "\\\n\t:sm=%s:", inet_ntoa(hp->subnet_mask));
|
||||
}
|
||||
if (hp->flags.swap_server) {
|
||||
fprintf(fp, "\\\n\t:sw=%s:", inet_ntoa(hp->subnet_mask));
|
||||
}
|
||||
if (hp->flags.tftpdir) {
|
||||
fprintf(fp, "\\\n\t:td=%s:", hp->tftpdir->string);
|
||||
}
|
||||
/* NetBSD: rootpath (see above) */
|
||||
/* NetBSD: domainname (see above) */
|
||||
/* NetBSD: dumpfile (see above) */
|
||||
if (hp->flags.time_offset) {
|
||||
fprintf(fp, "\\\n\t:to=%ld:", hp->time_offset);
|
||||
}
|
||||
if (hp->flags.time_server) {
|
||||
fprintf(fp, "\\\n\t:ts=");
|
||||
list_ipaddresses(fp, hp->time_server);
|
||||
fprintf(fp, ":");
|
||||
}
|
||||
if (hp->flags.vm_cookie) {
|
||||
fprintf(fp, "\\\n\t:vm=");
|
||||
if (!bcmp(hp->vm_cookie, vm_rfc1048, 4)) {
|
||||
fprintf(fp, "rfc1048:");
|
||||
} else if (!bcmp(hp->vm_cookie, vm_cmu, 4)) {
|
||||
fprintf(fp, "cmu:");
|
||||
} else {
|
||||
fprintf(fp, "%d.%d.%d.%d:",
|
||||
(int) ((hp->vm_cookie)[0]),
|
||||
(int) ((hp->vm_cookie)[1]),
|
||||
(int) ((hp->vm_cookie)[2]),
|
||||
(int) ((hp->vm_cookie)[3]));
|
||||
}
|
||||
}
|
||||
if (hp->flags.nis_domain) {
|
||||
fprintf(fp, "\\\n\t:yd=%s:",
|
||||
hp->nis_domain->string);
|
||||
}
|
||||
if (hp->flags.nis_server) {
|
||||
fprintf(fp, "\\\n\t:ys=");
|
||||
list_ipaddresses(fp, hp->nis_server);
|
||||
fprintf(fp, ":");
|
||||
}
|
||||
/*
|
||||
* XXX - Add new tags here (or above,
|
||||
* so they print in alphabetical order).
|
||||
*/
|
||||
|
||||
if (hp->flags.generic) {
|
||||
dump_generic(fp, hp->generic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dump_generic(fp, generic)
|
||||
FILE *fp;
|
||||
struct shared_bindata *generic;
|
||||
{
|
||||
u_char *bp = generic->data;
|
||||
u_char *ep = bp + generic->length;
|
||||
u_char tag;
|
||||
int len;
|
||||
|
||||
while (bp < ep) {
|
||||
tag = *bp++;
|
||||
if (tag == TAG_PAD)
|
||||
continue;
|
||||
if (tag == TAG_END)
|
||||
return;
|
||||
len = *bp++;
|
||||
if (bp + len > ep) {
|
||||
fprintf(fp, " #junk in generic! :");
|
||||
return;
|
||||
}
|
||||
fprintf(fp, "\\\n\t:T%d=", tag);
|
||||
while (len) {
|
||||
fprintf(fp, "%02X", *bp);
|
||||
bp++;
|
||||
len--;
|
||||
if (len)
|
||||
fprintf(fp, ".");
|
||||
}
|
||||
fprintf(fp, ":");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Dump an entire struct in_addr_list of IP addresses to the indicated file.
|
||||
*
|
||||
* The addresses are printed in standard ASCII "dot" notation and separated
|
||||
* from one another by a single space. A single leading space is also
|
||||
* printed before the first adddress.
|
||||
*
|
||||
* Null lists produce no output (and no error).
|
||||
*/
|
||||
|
||||
static void
|
||||
list_ipaddresses(fp, ipptr)
|
||||
FILE *fp;
|
||||
struct in_addr_list *ipptr;
|
||||
{
|
||||
unsigned count;
|
||||
struct in_addr *addrptr;
|
||||
|
||||
if (ipptr) {
|
||||
count = ipptr->addrcount;
|
||||
addrptr = ipptr->addr;
|
||||
while (count > 0) {
|
||||
fprintf(fp, "%s", inet_ntoa(*addrptr++));
|
||||
count--;
|
||||
if (count)
|
||||
fprintf(fp, ", ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-argdecl-indent: 4
|
||||
* c-continued-statement-offset: 4
|
||||
* c-continued-brace-offset: -4
|
||||
* c-label-offset: -4
|
||||
* c-brace-offset: 0
|
||||
* End:
|
||||
*/
|
374
libexec/bootpd/getether.c
Normal file
374
libexec/bootpd/getether.c
Normal file
@ -0,0 +1,374 @@
|
||||
/*
|
||||
* getether.c : get the ethernet address of an interface
|
||||
*
|
||||
* All of this code is quite system-specific. As you may well
|
||||
* guess, it took a good bit of detective work to figure out!
|
||||
*
|
||||
* If you figure out how to do this on another system,
|
||||
* please let me know. <gwr@mc.com>
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "report.h"
|
||||
#define EALEN 6
|
||||
|
||||
#if defined(ultrix) || (defined(__osf__) && defined(__alpha))
|
||||
/*
|
||||
* This is really easy on Ultrix! Thanks to
|
||||
* Harald Lundberg <hl@tekla.fi> for this code.
|
||||
*
|
||||
* The code here is not specific to the Alpha, but that was the
|
||||
* only symbol we could find to identify DEC's version of OSF.
|
||||
* (Perhaps we should just define DEC in the Makefile... -gwr)
|
||||
*/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h> /* struct ifdevea */
|
||||
|
||||
getether(ifname, eap)
|
||||
char *ifname, *eap;
|
||||
{
|
||||
int rc = -1;
|
||||
int fd;
|
||||
struct ifdevea phys;
|
||||
bzero(&phys, sizeof(phys));
|
||||
strcpy(phys.ifr_name, ifname);
|
||||
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||
report(LOG_ERR, "getether: socket(INET,DGRAM) failed");
|
||||
return -1;
|
||||
}
|
||||
if (ioctl(fd, SIOCRPHYSADDR, &phys) < 0) {
|
||||
report(LOG_ERR, "getether: ioctl SIOCRPHYSADDR failed");
|
||||
} else {
|
||||
bcopy(&phys.current_pa[0], eap, EALEN);
|
||||
rc = 0;
|
||||
}
|
||||
close(fd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define GETETHER
|
||||
#endif /* ultrix|osf1 */
|
||||
|
||||
|
||||
#ifdef SUNOS
|
||||
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/time.h> /* needed by net_if.h */
|
||||
#include <net/nit_if.h> /* for NIOCBIND */
|
||||
#include <net/if.h> /* for struct ifreq */
|
||||
|
||||
getether(ifname, eap)
|
||||
char *ifname; /* interface name from ifconfig structure */
|
||||
char *eap; /* Ether address (output) */
|
||||
{
|
||||
int rc = -1;
|
||||
|
||||
struct ifreq ifrnit;
|
||||
int nit;
|
||||
|
||||
bzero((char *) &ifrnit, sizeof(ifrnit));
|
||||
strncpy(&ifrnit.ifr_name[0], ifname, IFNAMSIZ);
|
||||
|
||||
nit = open("/dev/nit", 0);
|
||||
if (nit < 0) {
|
||||
report(LOG_ERR, "getether: open /dev/nit: %s",
|
||||
get_errmsg());
|
||||
return rc;
|
||||
}
|
||||
do {
|
||||
if (ioctl(nit, NIOCBIND, &ifrnit) < 0) {
|
||||
report(LOG_ERR, "getether: NIOCBIND on nit");
|
||||
break;
|
||||
}
|
||||
if (ioctl(nit, SIOCGIFADDR, &ifrnit) < 0) {
|
||||
report(LOG_ERR, "getether: SIOCGIFADDR on nit");
|
||||
break;
|
||||
}
|
||||
bcopy(&ifrnit.ifr_addr.sa_data[0], eap, EALEN);
|
||||
rc = 0;
|
||||
} while (0);
|
||||
close(nit);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define GETETHER
|
||||
#endif /* SUNOS */
|
||||
|
||||
|
||||
#if defined(__386BSD__) || defined(__NetBSD__)
|
||||
/* Thanks to John Brezak <brezak@ch.hp.com> for this code. */
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_types.h>
|
||||
|
||||
getether(ifname, eap)
|
||||
char *ifname; /* interface name from ifconfig structure */
|
||||
char *eap; /* Ether address (output) */
|
||||
{
|
||||
int fd, rc = -1;
|
||||
register int n;
|
||||
struct ifreq ibuf[16], ifr;
|
||||
struct ifconf ifc;
|
||||
register struct ifreq *ifrp, *ifend;
|
||||
|
||||
/* Fetch the interface configuration */
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
report(LOG_ERR, "getether: socket %s: %s", ifname, get_errmsg());
|
||||
return (fd);
|
||||
}
|
||||
ifc.ifc_len = sizeof(ibuf);
|
||||
ifc.ifc_buf = (caddr_t) ibuf;
|
||||
if (ioctl(fd, SIOCGIFCONF, (char *) &ifc) < 0 ||
|
||||
ifc.ifc_len < sizeof(struct ifreq)) {
|
||||
report(LOG_ERR, "getether: SIOCGIFCONF: %s", get_errmsg);
|
||||
goto out;
|
||||
}
|
||||
/* Search interface configuration list for link layer address. */
|
||||
ifrp = ibuf;
|
||||
ifend = (struct ifreq *) ((char *) ibuf + ifc.ifc_len);
|
||||
while (ifrp < ifend) {
|
||||
/* Look for interface */
|
||||
if (strcmp(ifname, ifrp->ifr_name) == 0 &&
|
||||
ifrp->ifr_addr.sa_family == AF_LINK &&
|
||||
((struct sockaddr_dl *) &ifrp->ifr_addr)->sdl_type == IFT_ETHER) {
|
||||
bcopy(LLADDR((struct sockaddr_dl *) &ifrp->ifr_addr), eap, EALEN);
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
/* Bump interface config pointer */
|
||||
n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
|
||||
if (n < sizeof(*ifrp))
|
||||
n = sizeof(*ifrp);
|
||||
ifrp = (struct ifreq *) ((char *) ifrp + n);
|
||||
}
|
||||
|
||||
out:
|
||||
close(fd);
|
||||
return (rc);
|
||||
}
|
||||
|
||||
#define GETETHER
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
|
||||
#ifdef SVR4
|
||||
/*
|
||||
* This is for "Streams TCP/IP" by Lachman Associates.
|
||||
* They sure made this cumbersome! -gwr
|
||||
*/
|
||||
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/dlpi.h>
|
||||
#include <stropts.h>
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
getether(ifname, eap)
|
||||
char *ifname; /* interface name from ifconfig structure */
|
||||
char *eap; /* Ether address (output) */
|
||||
{
|
||||
int rc = -1;
|
||||
char devname[32];
|
||||
char tmpbuf[sizeof(union DL_primitives) + 16];
|
||||
struct strbuf cbuf;
|
||||
int fd, flags;
|
||||
union DL_primitives *dlp;
|
||||
char *enaddr;
|
||||
int unit = -1; /* which unit to attach */
|
||||
|
||||
sprintf(devname, "/dev/%s", ifname);
|
||||
fd = open(devname, 2);
|
||||
if (fd < 0) {
|
||||
/* Try without the trailing digit. */
|
||||
char *p = devname + 5;
|
||||
while (isalpha(*p))
|
||||
p++;
|
||||
if (isdigit(*p)) {
|
||||
unit = *p - '0';
|
||||
*p = '\0';
|
||||
}
|
||||
fd = open(devname, 2);
|
||||
if (fd < 0) {
|
||||
report(LOG_ERR, "getether: open %s: %s",
|
||||
devname, get_errmsg());
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
#ifdef DL_ATTACH_REQ
|
||||
/*
|
||||
* If this is a "Style 2" DLPI, then we must "attach" first
|
||||
* to tell the driver which unit (board, port) we want.
|
||||
* For now, decide this based on the device name.
|
||||
* (Should do "info_req" and check dl_provider_style ...)
|
||||
*/
|
||||
if (unit >= 0) {
|
||||
memset(tmpbuf, 0, sizeof(tmpbuf));
|
||||
dlp = (union DL_primitives *) tmpbuf;
|
||||
dlp->dl_primitive = DL_ATTACH_REQ;
|
||||
dlp->attach_req.dl_ppa = unit;
|
||||
cbuf.buf = tmpbuf;
|
||||
cbuf.len = DL_ATTACH_REQ_SIZE;
|
||||
if (putmsg(fd, &cbuf, NULL, 0) < 0) {
|
||||
report(LOG_ERR, "getether: attach: putmsg: %s", get_errmsg());
|
||||
goto out;
|
||||
}
|
||||
/* Recv the ack. */
|
||||
cbuf.buf = tmpbuf;
|
||||
cbuf.maxlen = sizeof(tmpbuf);
|
||||
flags = 0;
|
||||
if (getmsg(fd, &cbuf, NULL, &flags) < 0) {
|
||||
report(LOG_ERR, "getether: attach: getmsg: %s", get_errmsg());
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* Check the type, etc.
|
||||
*/
|
||||
if (dlp->dl_primitive == DL_ERROR_ACK) {
|
||||
report(LOG_ERR, "getether: attach: dlpi_errno=%d, unix_errno=%d",
|
||||
dlp->error_ack.dl_errno,
|
||||
dlp->error_ack.dl_unix_errno);
|
||||
goto out;
|
||||
}
|
||||
if (dlp->dl_primitive != DL_OK_ACK) {
|
||||
report(LOG_ERR, "getether: attach: not OK or ERROR");
|
||||
goto out;
|
||||
}
|
||||
} /* unit >= 0 */
|
||||
#endif /* DL_ATTACH_REQ */
|
||||
|
||||
/*
|
||||
* Get the Ethernet address the same way the ARP module
|
||||
* does when it is pushed onto a new stream (bind).
|
||||
* One should instead be able just do an dl_info_req
|
||||
* but many drivers do not supply the hardware address
|
||||
* in the response to dl_info_req (they MUST supply it
|
||||
* for dl_bind_ack because the ARP module requires it).
|
||||
*/
|
||||
memset(tmpbuf, 0, sizeof(tmpbuf));
|
||||
dlp = (union DL_primitives *) tmpbuf;
|
||||
dlp->dl_primitive = DL_BIND_REQ;
|
||||
dlp->bind_req.dl_sap = 0x8FF; /* XXX - Unused SAP */
|
||||
cbuf.buf = tmpbuf;
|
||||
cbuf.len = DL_BIND_REQ_SIZE;
|
||||
if (putmsg(fd, &cbuf, NULL, 0) < 0) {
|
||||
report(LOG_ERR, "getether: bind: putmsg: %s", get_errmsg());
|
||||
goto out;
|
||||
}
|
||||
/* Recv the ack. */
|
||||
cbuf.buf = tmpbuf;
|
||||
cbuf.maxlen = sizeof(tmpbuf);
|
||||
flags = 0;
|
||||
if (getmsg(fd, &cbuf, NULL, &flags) < 0) {
|
||||
report(LOG_ERR, "getether: bind: getmsg: %s", get_errmsg());
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* Check the type, etc.
|
||||
*/
|
||||
if (dlp->dl_primitive == DL_ERROR_ACK) {
|
||||
report(LOG_ERR, "getether: bind: dlpi_errno=%d, unix_errno=%d",
|
||||
dlp->error_ack.dl_errno,
|
||||
dlp->error_ack.dl_unix_errno);
|
||||
goto out;
|
||||
}
|
||||
if (dlp->dl_primitive != DL_BIND_ACK) {
|
||||
report(LOG_ERR, "getether: bind: not OK or ERROR");
|
||||
goto out;
|
||||
}
|
||||
if (dlp->bind_ack.dl_addr_offset == 0) {
|
||||
report(LOG_ERR, "getether: bind: ack has no address");
|
||||
goto out;
|
||||
}
|
||||
if (dlp->bind_ack.dl_addr_length < EALEN) {
|
||||
report(LOG_ERR, "getether: bind: ack address truncated");
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* Copy the Ethernet address out of the message.
|
||||
*/
|
||||
enaddr = tmpbuf + dlp->bind_ack.dl_addr_offset;
|
||||
memcpy(eap, enaddr, EALEN);
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
close(fd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define GETETHER
|
||||
#endif /* SVR4 */
|
||||
|
||||
|
||||
#ifdef linux
|
||||
/*
|
||||
* This is really easy on Linux! This version (for linux)
|
||||
* written by Nigel Metheringham <nigelm@ohm.york.ac.uk>
|
||||
*
|
||||
* The code is almost identical to the Ultrix code - however
|
||||
* the names are different to confuse the innocent :-)
|
||||
* Most of this code was stolen from the Ultrix bit above.
|
||||
*/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h> /* struct ifreq */
|
||||
|
||||
/* In a properly configured system this should be either sys/socketio.h
|
||||
or sys/sockios.h, but on my distribution these don't line up correctly */
|
||||
#include <linux/sockios.h> /* Needed for IOCTL defs */
|
||||
|
||||
getether(ifname, eap)
|
||||
char *ifname, *eap;
|
||||
{
|
||||
int rc = -1;
|
||||
int fd;
|
||||
struct ifreq phys;
|
||||
bzero(&phys, sizeof(phys));
|
||||
strcpy(phys.ifr_name, ifname);
|
||||
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||
report(LOG_ERR, "getether: socket(INET,DGRAM) failed");
|
||||
return -1;
|
||||
}
|
||||
if (ioctl(fd, SIOCGIFHWADDR, &phys) < 0) {
|
||||
report(LOG_ERR, "getether: ioctl SIOCGIFHWADDR failed");
|
||||
} else {
|
||||
bcopy(phys.ifr_hwaddr, eap, EALEN);
|
||||
rc = 0;
|
||||
}
|
||||
close(fd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define GETETHER
|
||||
#endif /* linux */
|
||||
|
||||
|
||||
/* If we don't know how on this system, just return an error. */
|
||||
#ifndef GETETHER
|
||||
getether(ifname, eap)
|
||||
char *ifname, *eap;
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* !GETETHER */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-argdecl-indent: 4
|
||||
* c-continued-statement-offset: 4
|
||||
* c-continued-brace-offset: -4
|
||||
* c-label-offset: -4
|
||||
* c-brace-offset: 0
|
||||
* End:
|
||||
*/
|
145
libexec/bootpd/getif.c
Normal file
145
libexec/bootpd/getif.c
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* getif.c : get an interface structure
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#if defined(SUNOS) || defined(SVR4)
|
||||
#include <sys/sockio.h>
|
||||
#endif
|
||||
#ifdef SVR4
|
||||
#include <sys/stropts.h>
|
||||
#endif
|
||||
|
||||
#include <net/if.h> /* for struct ifreq */
|
||||
#include <netinet/in.h>
|
||||
|
||||
#ifndef NO_UNISTD
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <syslog.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "getif.h"
|
||||
#include "report.h"
|
||||
|
||||
#ifdef __bsdi__
|
||||
#define BSD 43
|
||||
#endif
|
||||
|
||||
static struct ifreq ifreq[10]; /* Holds interface configuration */
|
||||
static struct ifconf ifconf; /* points to ifreq */
|
||||
|
||||
static int nmatch();
|
||||
|
||||
/* Return a pointer to the interface struct for the passed address. */
|
||||
struct ifreq *
|
||||
getif(s, addrp)
|
||||
int s; /* socket file descriptor */
|
||||
struct in_addr *addrp; /* destination address on interface */
|
||||
{
|
||||
int maxmatch;
|
||||
int len, m, incr;
|
||||
struct ifreq *ifrq, *ifrmax;
|
||||
struct sockaddr_in *sip;
|
||||
char *p;
|
||||
|
||||
/* If no address was supplied, just return NULL. */
|
||||
if (!addrp)
|
||||
return (struct ifreq *) 0;
|
||||
|
||||
/* Get the interface config if not done already. */
|
||||
if (ifconf.ifc_len == 0) {
|
||||
#ifdef SVR4
|
||||
/*
|
||||
* SysVr4 returns garbage if you do this the obvious way!
|
||||
* This one took a while to figure out... -gwr
|
||||
*/
|
||||
struct strioctl ioc;
|
||||
ioc.ic_cmd = SIOCGIFCONF;
|
||||
ioc.ic_timout = 0;
|
||||
ioc.ic_len = sizeof(ifreq);
|
||||
ioc.ic_dp = (char *) ifreq;
|
||||
m = ioctl(s, I_STR, (char *) &ioc);
|
||||
ifconf.ifc_len = ioc.ic_len;
|
||||
ifconf.ifc_req = ifreq;
|
||||
#else /* SVR4 */
|
||||
ifconf.ifc_len = sizeof(ifreq);
|
||||
ifconf.ifc_req = ifreq;
|
||||
m = ioctl(s, SIOCGIFCONF, (caddr_t) & ifconf);
|
||||
#endif /* SVR4 */
|
||||
if ((m < 0) || (ifconf.ifc_len <= 0)) {
|
||||
report(LOG_ERR, "ioctl SIOCGIFCONF");
|
||||
return (struct ifreq *) 0;
|
||||
}
|
||||
}
|
||||
maxmatch = 7; /* this many bits or less... */
|
||||
ifrmax = (struct ifreq *) 0;/* ... is not a valid match */
|
||||
p = (char *) ifreq;
|
||||
len = ifconf.ifc_len;
|
||||
while (len > 0) {
|
||||
ifrq = (struct ifreq *) p;
|
||||
sip = (struct sockaddr_in *) &ifrq->ifr_addr;
|
||||
m = nmatch(addrp, &(sip->sin_addr));
|
||||
if (m > maxmatch) {
|
||||
maxmatch = m;
|
||||
ifrmax = ifrq;
|
||||
}
|
||||
/* XXX - Could this be just #ifndef IFNAMSIZ instead? -gwr */
|
||||
#if (BSD - 0) < 43
|
||||
/* BSD not defined or earlier than 4.3 */
|
||||
incr = sizeof(*ifrq);
|
||||
#else /* NetBSD */
|
||||
incr = ifrq->ifr_addr.sa_len + IFNAMSIZ;
|
||||
#endif /* NetBSD */
|
||||
|
||||
p += incr;
|
||||
len -= incr;
|
||||
}
|
||||
|
||||
return ifrmax;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of leading bits matching in the
|
||||
* internet addresses supplied.
|
||||
*/
|
||||
static int
|
||||
nmatch(ca, cb)
|
||||
u_char *ca, *cb; /* ptrs to IP address, network order */
|
||||
{
|
||||
u_int m = 0; /* count of matching bits */
|
||||
u_int n = 4; /* bytes left, then bitmask */
|
||||
|
||||
/* Count matching bytes. */
|
||||
while (n && (*ca == *cb)) {
|
||||
ca++;
|
||||
cb++;
|
||||
m += 8;
|
||||
n--;
|
||||
}
|
||||
/* Now count matching bits. */
|
||||
if (n) {
|
||||
n = 0x80;
|
||||
while (n && ((*ca & n) == (*cb & n))) {
|
||||
m++;
|
||||
n >>= 1;
|
||||
}
|
||||
}
|
||||
return (m);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-argdecl-indent: 4
|
||||
* c-continued-statement-offset: 4
|
||||
* c-continued-brace-offset: -4
|
||||
* c-label-offset: -4
|
||||
* c-brace-offset: 0
|
||||
* End:
|
||||
*/
|
7
libexec/bootpd/getif.h
Normal file
7
libexec/bootpd/getif.h
Normal file
@ -0,0 +1,7 @@
|
||||
/* getif.h */
|
||||
|
||||
#ifdef __STDC__
|
||||
extern struct ifreq *getif(int, struct in_addr *);
|
||||
#else
|
||||
extern struct ifreq *getif();
|
||||
#endif
|
425
libexec/bootpd/hash.c
Normal file
425
libexec/bootpd/hash.c
Normal file
@ -0,0 +1,425 @@
|
||||
/************************************************************************
|
||||
Copyright 1988, 1991 by Carnegie Mellon University
|
||||
|
||||
All Rights Reserved
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted, provided
|
||||
that the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation, and that the name of Carnegie Mellon University not be used
|
||||
in advertising or publicity pertaining to distribution of the software
|
||||
without specific, written prior permission.
|
||||
|
||||
CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
|
||||
IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
SOFTWARE.
|
||||
************************************************************************/
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$Id: hash.c,v 1.1.1.1 1994/09/10 14:44:55 csgr Exp $";
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Generalized hash table ADT
|
||||
*
|
||||
* Provides multiple, dynamically-allocated, variable-sized hash tables on
|
||||
* various data and keys.
|
||||
*
|
||||
* This package attempts to follow some of the coding conventions suggested
|
||||
* by Bob Sidebotham and the AFS Clean Code Committee of the
|
||||
* Information Technology Center at Carnegie Mellon.
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef USE_BFUNCS
|
||||
#include <memory.h>
|
||||
/* Yes, memcpy is OK here (no overlapped copies). */
|
||||
#define bcopy(a,b,c) memcpy(b,a,c)
|
||||
#define bzero(p,l) memset(p,0,l)
|
||||
#define bcmp(a,b,c) memcmp(a,b,c)
|
||||
#endif
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This can be changed to make internal routines visible to debuggers, etc.
|
||||
*/
|
||||
#ifndef PRIVATE
|
||||
#define PRIVATE static
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
#define P(args) args
|
||||
#else
|
||||
#define P(args) ()
|
||||
#endif
|
||||
|
||||
PRIVATE void hashi_FreeMembers P((hash_member *, hash_freefp));
|
||||
|
||||
#undef P
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Hash table initialization routine.
|
||||
*
|
||||
* This routine creates and intializes a hash table of size "tablesize"
|
||||
* entries. Successful calls return a pointer to the hash table (which must
|
||||
* be passed to other hash routines to identify the hash table). Failed
|
||||
* calls return NULL.
|
||||
*/
|
||||
|
||||
hash_tbl *
|
||||
hash_Init(tablesize)
|
||||
unsigned tablesize;
|
||||
{
|
||||
register hash_tbl *hashtblptr;
|
||||
register unsigned totalsize;
|
||||
|
||||
if (tablesize > 0) {
|
||||
totalsize = sizeof(hash_tbl)
|
||||
+ sizeof(hash_member *) * (tablesize - 1);
|
||||
hashtblptr = (hash_tbl *) malloc(totalsize);
|
||||
if (hashtblptr) {
|
||||
bzero((char *) hashtblptr, totalsize);
|
||||
hashtblptr->size = tablesize; /* Success! */
|
||||
hashtblptr->bucketnum = 0;
|
||||
hashtblptr->member = (hashtblptr->table)[0];
|
||||
}
|
||||
} else {
|
||||
hashtblptr = NULL; /* Disallow zero-length tables */
|
||||
}
|
||||
return hashtblptr; /* NULL if failure */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Frees an entire linked list of bucket members (used in the open
|
||||
* hashing scheme). Does nothing if the passed pointer is NULL.
|
||||
*/
|
||||
|
||||
PRIVATE void
|
||||
hashi_FreeMembers(bucketptr, free_data)
|
||||
hash_member *bucketptr;
|
||||
hash_freefp free_data;
|
||||
{
|
||||
hash_member *nextbucket;
|
||||
while (bucketptr) {
|
||||
nextbucket = bucketptr->next;
|
||||
(*free_data) (bucketptr->data);
|
||||
free((char *) bucketptr);
|
||||
bucketptr = nextbucket;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This routine re-initializes the hash table. It frees all the allocated
|
||||
* memory and resets all bucket pointers to NULL.
|
||||
*/
|
||||
|
||||
void
|
||||
hash_Reset(hashtable, free_data)
|
||||
hash_tbl *hashtable;
|
||||
hash_freefp free_data;
|
||||
{
|
||||
hash_member **bucketptr;
|
||||
unsigned i;
|
||||
|
||||
bucketptr = hashtable->table;
|
||||
for (i = 0; i < hashtable->size; i++) {
|
||||
hashi_FreeMembers(*bucketptr, free_data);
|
||||
*bucketptr++ = NULL;
|
||||
}
|
||||
hashtable->bucketnum = 0;
|
||||
hashtable->member = (hashtable->table)[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Generic hash function to calculate a hash code from the given string.
|
||||
*
|
||||
* For each byte of the string, this function left-shifts the value in an
|
||||
* accumulator and then adds the byte into the accumulator. The contents of
|
||||
* the accumulator is returned after the entire string has been processed.
|
||||
* It is assumed that this result will be used as the "hashcode" parameter in
|
||||
* calls to other functions in this package. These functions automatically
|
||||
* adjust the hashcode for the size of each hashtable.
|
||||
*
|
||||
* This algorithm probably works best when the hash table size is a prime
|
||||
* number.
|
||||
*
|
||||
* Hopefully, this function is better than the previous one which returned
|
||||
* the sum of the squares of all the bytes. I'm still open to other
|
||||
* suggestions for a default hash function. The programmer is more than
|
||||
* welcome to supply his/her own hash function as that is one of the design
|
||||
* features of this package.
|
||||
*/
|
||||
|
||||
unsigned
|
||||
hash_HashFunction(string, len)
|
||||
unsigned char *string;
|
||||
register unsigned len;
|
||||
{
|
||||
register unsigned accum;
|
||||
|
||||
accum = 0;
|
||||
for (; len > 0; len--) {
|
||||
accum <<= 1;
|
||||
accum += (unsigned) (*string++ & 0xFF);
|
||||
}
|
||||
return accum;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Returns TRUE if at least one entry for the given key exists; FALSE
|
||||
* otherwise.
|
||||
*/
|
||||
|
||||
int
|
||||
hash_Exists(hashtable, hashcode, compare, key)
|
||||
hash_tbl *hashtable;
|
||||
unsigned hashcode;
|
||||
hash_cmpfp compare;
|
||||
hash_datum *key;
|
||||
{
|
||||
register hash_member *memberptr;
|
||||
|
||||
memberptr = (hashtable->table)[hashcode % (hashtable->size)];
|
||||
while (memberptr) {
|
||||
if ((*compare) (key, memberptr->data)) {
|
||||
return TRUE; /* Entry does exist */
|
||||
}
|
||||
memberptr = memberptr->next;
|
||||
}
|
||||
return FALSE; /* Entry does not exist */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Insert the data item "element" into the hash table using "hashcode"
|
||||
* to determine the bucket number, and "compare" and "key" to determine
|
||||
* its uniqueness.
|
||||
*
|
||||
* If the insertion is successful 0 is returned. If a matching entry
|
||||
* already exists in the given bucket of the hash table, or some other error
|
||||
* occurs, -1 is returned and the insertion is not done.
|
||||
*/
|
||||
|
||||
int
|
||||
hash_Insert(hashtable, hashcode, compare, key, element)
|
||||
hash_tbl *hashtable;
|
||||
unsigned hashcode;
|
||||
hash_cmpfp compare;
|
||||
hash_datum *key, *element;
|
||||
{
|
||||
hash_member *temp;
|
||||
|
||||
hashcode %= hashtable->size;
|
||||
if (hash_Exists(hashtable, hashcode, compare, key)) {
|
||||
return -1; /* At least one entry already exists */
|
||||
}
|
||||
temp = (hash_member *) malloc(sizeof(hash_member));
|
||||
if (!temp)
|
||||
return -1; /* malloc failed! */
|
||||
|
||||
temp->data = element;
|
||||
temp->next = (hashtable->table)[hashcode];
|
||||
(hashtable->table)[hashcode] = temp;
|
||||
return 0; /* Success */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Delete all data elements which match the given key. If at least one
|
||||
* element is found and the deletion is successful, 0 is returned.
|
||||
* If no matching elements can be found in the hash table, -1 is returned.
|
||||
*/
|
||||
|
||||
int
|
||||
hash_Delete(hashtable, hashcode, compare, key, free_data)
|
||||
hash_tbl *hashtable;
|
||||
unsigned hashcode;
|
||||
hash_cmpfp compare;
|
||||
hash_datum *key;
|
||||
hash_freefp free_data;
|
||||
{
|
||||
hash_member *memberptr, *tempptr;
|
||||
hash_member *previous = NULL;
|
||||
int retval;
|
||||
|
||||
retval = -1;
|
||||
hashcode %= hashtable->size;
|
||||
|
||||
/*
|
||||
* Delete the first member of the list if it matches. Since this moves
|
||||
* the second member into the first position we have to keep doing this
|
||||
* over and over until it no longer matches.
|
||||
*/
|
||||
memberptr = (hashtable->table)[hashcode];
|
||||
while (memberptr && (*compare) (key, memberptr->data)) {
|
||||
(hashtable->table)[hashcode] = memberptr->next;
|
||||
/*
|
||||
* Stop hashi_FreeMembers() from deleting the whole list!
|
||||
*/
|
||||
memberptr->next = NULL;
|
||||
hashi_FreeMembers(memberptr, free_data);
|
||||
memberptr = (hashtable->table)[hashcode];
|
||||
retval = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now traverse the rest of the list
|
||||
*/
|
||||
if (memberptr) {
|
||||
previous = memberptr;
|
||||
memberptr = memberptr->next;
|
||||
}
|
||||
while (memberptr) {
|
||||
if ((*compare) (key, memberptr->data)) {
|
||||
tempptr = memberptr;
|
||||
previous->next = memberptr = memberptr->next;
|
||||
/*
|
||||
* Put the brakes on hashi_FreeMembers(). . . .
|
||||
*/
|
||||
tempptr->next = NULL;
|
||||
hashi_FreeMembers(tempptr, free_data);
|
||||
retval = 0;
|
||||
} else {
|
||||
previous = memberptr;
|
||||
memberptr = memberptr->next;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Locate and return the data entry associated with the given key.
|
||||
*
|
||||
* If the data entry is found, a pointer to it is returned. Otherwise,
|
||||
* NULL is returned.
|
||||
*/
|
||||
|
||||
hash_datum *
|
||||
hash_Lookup(hashtable, hashcode, compare, key)
|
||||
hash_tbl *hashtable;
|
||||
unsigned hashcode;
|
||||
hash_cmpfp compare;
|
||||
hash_datum *key;
|
||||
{
|
||||
hash_member *memberptr;
|
||||
|
||||
memberptr = (hashtable->table)[hashcode % (hashtable->size)];
|
||||
while (memberptr) {
|
||||
if ((*compare) (key, memberptr->data)) {
|
||||
return (memberptr->data);
|
||||
}
|
||||
memberptr = memberptr->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Return the next available entry in the hashtable for a linear search
|
||||
*/
|
||||
|
||||
hash_datum *
|
||||
hash_NextEntry(hashtable)
|
||||
hash_tbl *hashtable;
|
||||
{
|
||||
register unsigned bucket;
|
||||
register hash_member *memberptr;
|
||||
|
||||
/*
|
||||
* First try to pick up where we left off.
|
||||
*/
|
||||
memberptr = hashtable->member;
|
||||
if (memberptr) {
|
||||
hashtable->member = memberptr->next; /* Set up for next call */
|
||||
return memberptr->data; /* Return the data */
|
||||
}
|
||||
/*
|
||||
* We hit the end of a chain, so look through the array of buckets
|
||||
* until we find a new chain (non-empty bucket) or run out of buckets.
|
||||
*/
|
||||
bucket = hashtable->bucketnum + 1;
|
||||
while ((bucket < hashtable->size) &&
|
||||
!(memberptr = (hashtable->table)[bucket])) {
|
||||
bucket++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if we ran out of buckets.
|
||||
*/
|
||||
if (bucket >= hashtable->size) {
|
||||
/*
|
||||
* Reset to top of table for next call.
|
||||
*/
|
||||
hashtable->bucketnum = 0;
|
||||
hashtable->member = (hashtable->table)[0];
|
||||
/*
|
||||
* But return end-of-table indication to the caller this time.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* Must have found a non-empty bucket.
|
||||
*/
|
||||
hashtable->bucketnum = bucket;
|
||||
hashtable->member = memberptr->next; /* Set up for next call */
|
||||
return memberptr->data; /* Return the data */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Return the first entry in a hash table for a linear search
|
||||
*/
|
||||
|
||||
hash_datum *
|
||||
hash_FirstEntry(hashtable)
|
||||
hash_tbl *hashtable;
|
||||
{
|
||||
hashtable->bucketnum = 0;
|
||||
hashtable->member = (hashtable->table)[0];
|
||||
return hash_NextEntry(hashtable);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-argdecl-indent: 4
|
||||
* c-continued-statement-offset: 4
|
||||
* c-continued-brace-offset: -4
|
||||
* c-label-offset: -4
|
||||
* c-brace-offset: 0
|
||||
* End:
|
||||
*/
|
158
libexec/bootpd/hash.h
Normal file
158
libexec/bootpd/hash.h
Normal file
@ -0,0 +1,158 @@
|
||||
#ifndef HASH_H
|
||||
#define HASH_H
|
||||
/* hash.h */
|
||||
/************************************************************************
|
||||
Copyright 1988, 1991 by Carnegie Mellon University
|
||||
|
||||
All Rights Reserved
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted, provided
|
||||
that the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation, and that the name of Carnegie Mellon University not be used
|
||||
in advertising or publicity pertaining to distribution of the software
|
||||
without specific, written prior permission.
|
||||
|
||||
CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
|
||||
IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
SOFTWARE.
|
||||
************************************************************************/
|
||||
|
||||
/*
|
||||
* Generalized hash table ADT
|
||||
*
|
||||
* Provides multiple, dynamically-allocated, variable-sized hash tables on
|
||||
* various data and keys.
|
||||
*
|
||||
* This package attempts to follow some of the coding conventions suggested
|
||||
* by Bob Sidebotham and the AFS Clean Code Committee.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* The user must supply the following:
|
||||
*
|
||||
* 1. A comparison function which is declared as:
|
||||
*
|
||||
* int compare(data1, data2)
|
||||
* hash_datum *data1, *data2;
|
||||
*
|
||||
* This function must compare the desired fields of data1 and
|
||||
* data2 and return TRUE (1) if the data should be considered
|
||||
* equivalent (i.e. have the same key value) or FALSE (0)
|
||||
* otherwise. This function is called through a pointer passed to
|
||||
* the various hashtable functions (thus pointers to different
|
||||
* functions may be passed to effect different tests on different
|
||||
* hash tables).
|
||||
*
|
||||
* Internally, all the functions of this package always call the
|
||||
* compare function with the "key" parameter as the first parameter,
|
||||
* and a full data element as the second parameter. Thus, the key
|
||||
* and element arguments to functions such as hash_Lookup() may
|
||||
* actually be of different types and the programmer may provide a
|
||||
* compare function which compares the two different object types
|
||||
* as desired.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* int compare(key, element)
|
||||
* char *key;
|
||||
* struct some_complex_structure *element;
|
||||
* {
|
||||
* return !strcmp(key, element->name);
|
||||
* }
|
||||
*
|
||||
* key = "John C. Doe"
|
||||
* element = &some_complex_structure
|
||||
* hash_Lookup(table, hashcode, compare, key);
|
||||
*
|
||||
* 2. A hash function yielding an unsigned integer value to be used
|
||||
* as the hashcode (index into the hashtable). Thus, the user
|
||||
* may hash on whatever data is desired and may use several
|
||||
* different hash functions for various different hash tables.
|
||||
* The actual hash table index will be the passed hashcode modulo
|
||||
* the hash table size.
|
||||
*
|
||||
* A generalized hash function, hash_HashFunction(), is included
|
||||
* with this package to make things a little easier. It is not
|
||||
* guarenteed to use the best hash algorithm in existence. . . .
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Various hash table definitions
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Define "hash_datum" as a universal data type
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
typedef void hash_datum;
|
||||
#else
|
||||
typedef char hash_datum;
|
||||
#endif
|
||||
|
||||
typedef struct hash_memberstruct hash_member;
|
||||
typedef struct hash_tblstruct hash_tbl;
|
||||
typedef struct hash_tblstruct_hdr hash_tblhdr;
|
||||
|
||||
struct hash_memberstruct {
|
||||
hash_member *next;
|
||||
hash_datum *data;
|
||||
};
|
||||
|
||||
struct hash_tblstruct_hdr {
|
||||
unsigned size, bucketnum;
|
||||
hash_member *member;
|
||||
};
|
||||
|
||||
struct hash_tblstruct {
|
||||
unsigned size, bucketnum;
|
||||
hash_member *member; /* Used for linear dump */
|
||||
hash_member *table[1]; /* Dynamically extended */
|
||||
};
|
||||
|
||||
/* ANSI function prototypes or empty arg list? */
|
||||
#ifdef __STDC__
|
||||
#define P(args) args
|
||||
#else
|
||||
#define P(args) ()
|
||||
#endif
|
||||
|
||||
typedef int (*hash_cmpfp) P((hash_datum *, hash_datum *));
|
||||
typedef void (*hash_freefp) P((hash_datum *));
|
||||
|
||||
extern hash_tbl *hash_Init P((u_int tablesize));
|
||||
|
||||
extern void hash_Reset P((hash_tbl *tbl, hash_freefp));
|
||||
|
||||
extern unsigned hash_HashFunction P((u_char *str, u_int len));
|
||||
|
||||
extern int hash_Exists P((hash_tbl *, u_int code,
|
||||
hash_cmpfp, hash_datum *key));
|
||||
|
||||
extern int hash_Insert P((hash_tbl *, u_int code,
|
||||
hash_cmpfp, hash_datum *key,
|
||||
hash_datum *element));
|
||||
|
||||
extern int hash_Delete P((hash_tbl *, u_int code,
|
||||
hash_cmpfp, hash_datum *key,
|
||||
hash_freefp));
|
||||
|
||||
extern hash_datum *hash_Lookup P((hash_tbl *, u_int code,
|
||||
hash_cmpfp, hash_datum *key));
|
||||
|
||||
extern hash_datum *hash_FirstEntry P((hash_tbl *));
|
||||
|
||||
extern hash_datum *hash_NextEntry P((hash_tbl *));
|
||||
|
||||
#undef P
|
||||
|
||||
#endif /* HASH_H */
|
294
libexec/bootpd/hwaddr.c
Normal file
294
libexec/bootpd/hwaddr.c
Normal file
@ -0,0 +1,294 @@
|
||||
/*
|
||||
* hwaddr.c - routines that deal with hardware addresses.
|
||||
* (i.e. Ethernet)
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#if defined(SUNOS) || defined(SVR4)
|
||||
#include <sys/sockio.h>
|
||||
#endif
|
||||
#ifdef SVR4
|
||||
#include <sys/stream.h>
|
||||
#include <stropts.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include <net/if_arp.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#ifndef NO_UNISTD
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <syslog.h>
|
||||
|
||||
#ifndef USE_BFUNCS
|
||||
/* Yes, memcpy is OK here (no overlapped copies). */
|
||||
#include <memory.h>
|
||||
#define bcopy(a,b,c) memcpy(b,a,c)
|
||||
#define bzero(p,l) memset(p,0,l)
|
||||
#define bcmp(a,b,c) memcmp(a,b,c)
|
||||
#endif
|
||||
|
||||
/* For BSD 4.4, set arp entry by writing to routing socket */
|
||||
#if defined(BSD)
|
||||
#if BSD >= 199306
|
||||
extern int bsd_arp_set __P((struct in_addr *, char *, int));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "bptypes.h"
|
||||
#include "hwaddr.h"
|
||||
#include "report.h"
|
||||
|
||||
extern int debug;
|
||||
|
||||
/*
|
||||
* Hardware address lengths (in bytes) and network name based on hardware
|
||||
* type code. List in order specified by Assigned Numbers RFC; Array index
|
||||
* is hardware type code. Entries marked as zero are unknown to the author
|
||||
* at this time. . . .
|
||||
*/
|
||||
|
||||
struct hwinfo hwinfolist[] =
|
||||
{
|
||||
{0, "Reserved"}, /* Type 0: Reserved (don't use this) */
|
||||
{6, "Ethernet"}, /* Type 1: 10Mb Ethernet (48 bits) */
|
||||
{1, "3Mb Ethernet"}, /* Type 2: 3Mb Ethernet (8 bits) */
|
||||
{0, "AX.25"}, /* Type 3: Amateur Radio AX.25 */
|
||||
{1, "ProNET"}, /* Type 4: Proteon ProNET Token Ring */
|
||||
{0, "Chaos"}, /* Type 5: Chaos */
|
||||
{6, "IEEE 802"}, /* Type 6: IEEE 802 Networks */
|
||||
{0, "ARCNET"} /* Type 7: ARCNET */
|
||||
};
|
||||
int hwinfocnt = sizeof(hwinfolist) / sizeof(hwinfolist[0]);
|
||||
|
||||
|
||||
/*
|
||||
* Setup the arp cache so that IP address 'ia' will be temporarily
|
||||
* bound to hardware address 'ha' of length 'len'.
|
||||
*/
|
||||
void
|
||||
setarp(s, ia, ha, len)
|
||||
int s; /* socket fd */
|
||||
struct in_addr *ia;
|
||||
u_char *ha;
|
||||
int len;
|
||||
{
|
||||
#ifdef SIOCSARP
|
||||
struct arpreq arpreq; /* Arp request ioctl block */
|
||||
struct sockaddr_in *si;
|
||||
#ifdef SVR4
|
||||
int fd;
|
||||
struct strioctl iocb;
|
||||
#endif /* SVR4 */
|
||||
|
||||
bzero((caddr_t) & arpreq, sizeof(arpreq));
|
||||
arpreq.arp_flags = ATF_INUSE | ATF_COM;
|
||||
|
||||
/* Set up the protocol address. */
|
||||
arpreq.arp_pa.sa_family = AF_INET;
|
||||
si = (struct sockaddr_in *) &arpreq.arp_pa;
|
||||
si->sin_addr = *ia;
|
||||
|
||||
/* Set up the hardware address. */
|
||||
bcopy(ha, arpreq.arp_ha.sa_data, len);
|
||||
|
||||
#ifdef SVR4
|
||||
/*
|
||||
* And now the stuff for System V Rel 4.x which does not
|
||||
* appear to allow SIOCxxx ioctls on a socket descriptor.
|
||||
* Thanks to several people: (all sent the same fix)
|
||||
* Barney Wolff <barney@databus.com>,
|
||||
* bear@upsys.se (Bj|rn Sj|holm),
|
||||
* Michael Kuschke <Michael.Kuschke@Materna.DE>,
|
||||
*/
|
||||
if ((fd=open("/dev/arp", O_RDWR)) < 0) {
|
||||
report(LOG_ERR, "open /dev/arp: %s\n", get_errmsg());
|
||||
}
|
||||
iocb.ic_cmd = SIOCSARP;
|
||||
iocb.ic_timout = 0;
|
||||
iocb.ic_dp = (char *)&arpreq;
|
||||
iocb.ic_len = sizeof(arpreq);
|
||||
if (ioctl(fd, I_STR, (caddr_t)&iocb) < 0) {
|
||||
report(LOG_ERR, "ioctl I_STR: %s\n", get_errmsg());
|
||||
}
|
||||
close (fd);
|
||||
|
||||
#else /* SVR4 */
|
||||
/*
|
||||
* On SunOS, the ioctl sometimes returns ENXIO, and it
|
||||
* appears to happen when the ARP cache entry you tried
|
||||
* to add is already in the cache. (Sigh...)
|
||||
* XXX - Should this error simply be ignored? -gwr
|
||||
*/
|
||||
if (ioctl(s, SIOCSARP, (caddr_t) & arpreq) < 0) {
|
||||
report(LOG_ERR, "ioctl SIOCSARP: %s", get_errmsg());
|
||||
}
|
||||
#endif /* SVR4 */
|
||||
#else /* SIOCSARP */
|
||||
#if defined(BSD) && (BSD >= 199306)
|
||||
bsd_arp_set(ia, ha, len);
|
||||
#else /* Not BSD 4.4, and SIOCSARP not defined */
|
||||
/*
|
||||
* Oh well, SIOCSARP is not defined. Just run arp(8).
|
||||
* XXX - Gag!
|
||||
*/
|
||||
char buf[256];
|
||||
int status;
|
||||
|
||||
sprintf(buf, "arp -s %s %s temp",
|
||||
inet_ntoa(*ia), haddrtoa(ha, len));
|
||||
if (debug > 2)
|
||||
report(LOG_INFO, buf);
|
||||
status = system(buf);
|
||||
if (status)
|
||||
report(LOG_ERR, "arp failed, exit code=0x%x", status);
|
||||
return;
|
||||
#endif /* ! 4.4 BSD */
|
||||
#endif /* SIOCSARP */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert a hardware address to an ASCII string.
|
||||
*/
|
||||
char *
|
||||
haddrtoa(haddr, hlen)
|
||||
u_char *haddr;
|
||||
int hlen;
|
||||
{
|
||||
static char haddrbuf[3 * MAXHADDRLEN + 1];
|
||||
char *bufptr;
|
||||
|
||||
if (hlen > MAXHADDRLEN)
|
||||
hlen = MAXHADDRLEN;
|
||||
|
||||
bufptr = haddrbuf;
|
||||
while (hlen > 0) {
|
||||
sprintf(bufptr, "%02X:", (unsigned) (*haddr++ & 0xFF));
|
||||
bufptr += 3;
|
||||
hlen--;
|
||||
}
|
||||
bufptr[-1] = 0;
|
||||
return (haddrbuf);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* haddr_conv802()
|
||||
* --------------
|
||||
*
|
||||
* Converts a backwards address to a canonical address and a canonical address
|
||||
* to a backwards address.
|
||||
*
|
||||
* INPUTS:
|
||||
* adr_in - pointer to six byte string to convert (unsigned char *)
|
||||
* addr_len - how many bytes to convert
|
||||
*
|
||||
* OUTPUTS:
|
||||
* addr_out - The string is updated to contain the converted address.
|
||||
*
|
||||
* CALLER:
|
||||
* many
|
||||
*
|
||||
* DATA:
|
||||
* Uses conv802table to bit-reverse the address bytes.
|
||||
*/
|
||||
|
||||
static u_char conv802table[256] =
|
||||
{
|
||||
/* 0x00 */ 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
|
||||
/* 0x08 */ 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
|
||||
/* 0x10 */ 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
|
||||
/* 0x18 */ 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
|
||||
/* 0x20 */ 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
|
||||
/* 0x28 */ 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
|
||||
/* 0x30 */ 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
|
||||
/* 0x38 */ 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
|
||||
/* 0x40 */ 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
|
||||
/* 0x48 */ 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
|
||||
/* 0x50 */ 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
|
||||
/* 0x58 */ 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
|
||||
/* 0x60 */ 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
|
||||
/* 0x68 */ 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
|
||||
/* 0x70 */ 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
|
||||
/* 0x78 */ 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
|
||||
/* 0x80 */ 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
|
||||
/* 0x88 */ 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
|
||||
/* 0x90 */ 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
|
||||
/* 0x98 */ 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
|
||||
/* 0xA0 */ 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
|
||||
/* 0xA8 */ 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
|
||||
/* 0xB0 */ 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
|
||||
/* 0xB8 */ 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
|
||||
/* 0xC0 */ 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
|
||||
/* 0xC8 */ 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
|
||||
/* 0xD0 */ 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
|
||||
/* 0xD8 */ 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
|
||||
/* 0xE0 */ 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
|
||||
/* 0xE8 */ 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
|
||||
/* 0xF0 */ 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
|
||||
/* 0xF8 */ 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF,
|
||||
};
|
||||
|
||||
void
|
||||
haddr_conv802(addr_in, addr_out, len)
|
||||
register u_char *addr_in, *addr_out;
|
||||
int len;
|
||||
{
|
||||
u_char *lim;
|
||||
|
||||
lim = addr_out + len;
|
||||
while (addr_out < lim)
|
||||
*addr_out++ = conv802table[*addr_in++];
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* For the record, here is a program to generate the
|
||||
* bit-reverse table above.
|
||||
*/
|
||||
static int
|
||||
bitrev(n)
|
||||
int n;
|
||||
{
|
||||
int i, r;
|
||||
|
||||
r = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
r <<= 1;
|
||||
r |= (n & 1);
|
||||
n >>= 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i <= 0xFF; i++) {
|
||||
if ((i & 7) == 0)
|
||||
printf("/* 0x%02X */", i);
|
||||
printf(" 0x%02X,", bitrev(i));
|
||||
if ((i & 7) == 7)
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-argdecl-indent: 4
|
||||
* c-continued-statement-offset: 4
|
||||
* c-continued-brace-offset: -4
|
||||
* c-label-offset: -4
|
||||
* c-brace-offset: 0
|
||||
* End:
|
||||
*/
|
39
libexec/bootpd/hwaddr.h
Normal file
39
libexec/bootpd/hwaddr.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* hwaddr.h */
|
||||
#ifndef HWADDR_H
|
||||
#define HWADDR_H
|
||||
|
||||
#define MAXHADDRLEN 8 /* Max hw address length in bytes */
|
||||
|
||||
/*
|
||||
* This structure holds information about a specific network type. The
|
||||
* length of the network hardware address is stored in "hlen".
|
||||
* The string pointed to by "name" is the cononical name of the network.
|
||||
*/
|
||||
struct hwinfo {
|
||||
unsigned int hlen;
|
||||
char *name;
|
||||
};
|
||||
|
||||
extern struct hwinfo hwinfolist[];
|
||||
extern int hwinfocnt;
|
||||
|
||||
#ifdef __STDC__
|
||||
#define P(args) args
|
||||
#else
|
||||
#define P(args) ()
|
||||
#endif
|
||||
|
||||
extern void setarp P((int, struct in_addr *, u_char *, int));
|
||||
extern char *haddrtoa P((u_char *, int));
|
||||
extern void haddr_conv802 P((u_char *, u_char *, int));
|
||||
|
||||
#undef P
|
||||
|
||||
/*
|
||||
* Return the length in bytes of a hardware address of the given type.
|
||||
* Return the canonical name of the network of the given type.
|
||||
*/
|
||||
#define haddrlength(type) ((hwinfolist[(int) (type)]).hlen)
|
||||
#define netname(type) ((hwinfolist[(int) (type)]).name)
|
||||
|
||||
#endif /* HWADDR_H */
|
126
libexec/bootpd/lookup.c
Normal file
126
libexec/bootpd/lookup.c
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* lookup.c - Lookup IP address, HW address, netmask
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#ifdef ETC_ETHERS
|
||||
#include <netinet/if_ether.h>
|
||||
extern int ether_hostton();
|
||||
#endif
|
||||
|
||||
#include <netdb.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#ifndef USE_BFUNCS
|
||||
#include <memory.h>
|
||||
/* Yes, memcpy is OK here (no overlapped copies). */
|
||||
#define bcopy(a,b,c) memcpy(b,a,c)
|
||||
#endif
|
||||
|
||||
#include "bootp.h"
|
||||
#include "lookup.h"
|
||||
#include "report.h"
|
||||
|
||||
/*
|
||||
* Lookup an Ethernet address and return it.
|
||||
* Return NULL if addr not found.
|
||||
*/
|
||||
u_char *
|
||||
lookup_hwa(hostname, htype)
|
||||
char *hostname;
|
||||
int htype;
|
||||
{
|
||||
switch (htype) {
|
||||
|
||||
/* XXX - How is this done on other systems? -gwr */
|
||||
#ifdef ETC_ETHERS
|
||||
case HTYPE_ETHERNET:
|
||||
case HTYPE_IEEE802:
|
||||
{
|
||||
static struct ether_addr ea;
|
||||
/* This does a lookup in /etc/ethers */
|
||||
if (ether_hostton(hostname, &ea)) {
|
||||
report(LOG_ERR, "no HW addr for host \"%s\"",
|
||||
hostname);
|
||||
return (u_char *) 0;
|
||||
}
|
||||
return (u_char *) & ea;
|
||||
}
|
||||
#endif /* ETC_ETHERS */
|
||||
|
||||
default:
|
||||
report(LOG_ERR, "no lookup for HW addr type %d", htype);
|
||||
} /* switch */
|
||||
|
||||
/* If the system can't do it, just return an error. */
|
||||
return (u_char *) 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Lookup an IP address.
|
||||
* Return non-zero on failure.
|
||||
*/
|
||||
int
|
||||
lookup_ipa(hostname, result)
|
||||
char *hostname;
|
||||
u_int32 *result;
|
||||
{
|
||||
struct hostent *hp;
|
||||
hp = gethostbyname(hostname);
|
||||
if (!hp)
|
||||
return -1;
|
||||
bcopy(hp->h_addr, result, sizeof(*result));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Lookup a netmask
|
||||
* Return non-zero on failure.
|
||||
*
|
||||
* XXX - This is OK as a default, but to really make this automatic,
|
||||
* we would need to get the subnet mask from the ether interface.
|
||||
* If this is wrong, specify the correct value in the bootptab.
|
||||
*/
|
||||
int
|
||||
lookup_netmask(addr, result)
|
||||
u_int32 addr; /* both in network order */
|
||||
u_int32 *result;
|
||||
{
|
||||
int32 m, a;
|
||||
|
||||
a = ntohl(addr);
|
||||
m = 0;
|
||||
|
||||
if (IN_CLASSA(a))
|
||||
m = IN_CLASSA_NET;
|
||||
|
||||
if (IN_CLASSB(a))
|
||||
m = IN_CLASSB_NET;
|
||||
|
||||
if (IN_CLASSC(a))
|
||||
m = IN_CLASSC_NET;
|
||||
|
||||
if (!m)
|
||||
return -1;
|
||||
*result = htonl(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-argdecl-indent: 4
|
||||
* c-continued-statement-offset: 4
|
||||
* c-continued-brace-offset: -4
|
||||
* c-label-offset: -4
|
||||
* c-brace-offset: 0
|
||||
* End:
|
||||
*/
|
15
libexec/bootpd/lookup.h
Normal file
15
libexec/bootpd/lookup.h
Normal file
@ -0,0 +1,15 @@
|
||||
/* lookup.h */
|
||||
|
||||
#include "bptypes.h" /* for int32, u_int32 */
|
||||
|
||||
#ifdef __STDC__
|
||||
#define P(args) args
|
||||
#else
|
||||
#define P(args) ()
|
||||
#endif
|
||||
|
||||
extern u_char *lookup_hwa P((char *hostname, int htype));
|
||||
extern int lookup_ipa P((char *hostname, u_int32 *addr));
|
||||
extern int lookup_netmask P((u_int32 addr, u_int32 *mask));
|
||||
|
||||
#undef P
|
3
libexec/bootpd/patchlevel.h
Normal file
3
libexec/bootpd/patchlevel.h
Normal file
@ -0,0 +1,3 @@
|
||||
/* patchlevel.h */
|
||||
#define VERSION "2.4"
|
||||
#define PATCHLEVEL 1
|
2097
libexec/bootpd/readfile.c
Normal file
2097
libexec/bootpd/readfile.c
Normal file
File diff suppressed because it is too large
Load Diff
19
libexec/bootpd/readfile.h
Normal file
19
libexec/bootpd/readfile.h
Normal file
@ -0,0 +1,19 @@
|
||||
/* readfile.h */
|
||||
|
||||
#include "bptypes.h"
|
||||
#include "hash.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
#define P(args) args
|
||||
#else
|
||||
#define P(args) ()
|
||||
#endif
|
||||
|
||||
extern boolean hwlookcmp P((hash_datum *, hash_datum *));
|
||||
extern boolean iplookcmp P((hash_datum *, hash_datum *));
|
||||
extern boolean nmcmp P((hash_datum *, hash_datum *));
|
||||
extern void readtab P((int));
|
||||
extern void rdtab_init P((void));
|
||||
|
||||
#undef P
|
||||
|
154
libexec/bootpd/report.c
Normal file
154
libexec/bootpd/report.c
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* report() - calls syslog
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "report.h"
|
||||
|
||||
#ifndef LOG_NDELAY
|
||||
#define LOG_NDELAY 0
|
||||
#endif
|
||||
#ifndef LOG_DAEMON
|
||||
#define LOG_DAEMON 0
|
||||
#endif
|
||||
#ifndef LOG_BOOTP
|
||||
#define LOG_BOOTP LOG_DAEMON
|
||||
#endif
|
||||
|
||||
extern int debug;
|
||||
extern char *progname;
|
||||
|
||||
/*
|
||||
* This is initialized so you get stderr until you call
|
||||
* report_init()
|
||||
*/
|
||||
static int stderr_only = 1;
|
||||
|
||||
void
|
||||
report_init(nolog)
|
||||
int nolog;
|
||||
{
|
||||
stderr_only = nolog;
|
||||
#ifdef SYSLOG
|
||||
if (!stderr_only) {
|
||||
openlog(progname, LOG_PID | LOG_NDELAY, LOG_BOOTP);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine reports errors and such via stderr and syslog() if
|
||||
* appopriate. It just helps avoid a lot of "#ifdef SYSLOG" constructs
|
||||
* from being scattered throughout the code.
|
||||
*
|
||||
* The syntax is identical to syslog(3), but %m is not considered special
|
||||
* for output to stderr (i.e. you'll see "%m" in the output. . .). Also,
|
||||
* control strings should normally end with \n since newlines aren't
|
||||
* automatically generated for stderr output (whereas syslog strips out all
|
||||
* newlines and adds its own at the end).
|
||||
*/
|
||||
|
||||
static char *levelnames[] = {
|
||||
#ifdef LOG_SALERT
|
||||
"level(0): ",
|
||||
"alert(1): ",
|
||||
"alert(2): ",
|
||||
"emerg(3): ",
|
||||
"error(4): ",
|
||||
"crit(5): ",
|
||||
"warn(6): ",
|
||||
"note(7): ",
|
||||
"info(8): ",
|
||||
"debug(9): ",
|
||||
"level(?): "
|
||||
#else
|
||||
"emerg(0): ",
|
||||
"alert(1): ",
|
||||
"crit(2): ",
|
||||
"error(3): ",
|
||||
"warn(4): ",
|
||||
"note(5): ",
|
||||
"info(6): ",
|
||||
"debug(7): ",
|
||||
"level(?): "
|
||||
#endif
|
||||
};
|
||||
static int numlevels = sizeof(levelnames) / sizeof(levelnames[0]);
|
||||
|
||||
|
||||
/*
|
||||
* Print a log message using syslog(3) and/or stderr.
|
||||
* The message passed in should not include a newline.
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
void
|
||||
report(int priority, char *fmt,...)
|
||||
#else
|
||||
/*VARARGS2*/
|
||||
void
|
||||
report(priority, fmt, va_alist)
|
||||
int priority;
|
||||
char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
static char buf[128];
|
||||
|
||||
if ((priority < 0) || (priority >= numlevels)) {
|
||||
priority = numlevels - 1;
|
||||
}
|
||||
#ifdef __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
vsprintf(buf, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
/*
|
||||
* Print the message
|
||||
*/
|
||||
if (stderr_only || (debug > 2)) {
|
||||
fprintf(stderr, "%s: %s %s\n",
|
||||
progname, levelnames[priority], buf);
|
||||
}
|
||||
#ifdef SYSLOG
|
||||
if (!stderr_only)
|
||||
syslog((priority | LOG_BOOTP), "%s", buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Return pointer to static string which gives full filesystem error message.
|
||||
*/
|
||||
char *
|
||||
get_errmsg()
|
||||
{
|
||||
extern int errno;
|
||||
extern char *strerror();
|
||||
|
||||
return strerror(errno);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-argdecl-indent: 4
|
||||
* c-continued-statement-offset: 4
|
||||
* c-continued-brace-offset: -4
|
||||
* c-label-offset: -4
|
||||
* c-brace-offset: 0
|
||||
* End:
|
||||
*/
|
13
libexec/bootpd/report.h
Normal file
13
libexec/bootpd/report.h
Normal file
@ -0,0 +1,13 @@
|
||||
/* report.h */
|
||||
|
||||
#ifdef __STDC__
|
||||
#define P(args) args
|
||||
#else
|
||||
#define P(args) ()
|
||||
#endif
|
||||
|
||||
extern void report_init P((int nolog));
|
||||
extern void report P((int, char *, ...));
|
||||
extern char *get_errmsg P((void));
|
||||
|
||||
#undef P
|
63
libexec/bootpd/syslog.conf
Normal file
63
libexec/bootpd/syslog.conf
Normal file
@ -0,0 +1,63 @@
|
||||
#
|
||||
# syslog configuration file for SunOS 4.X
|
||||
# (modified to do local2 separately)
|
||||
#
|
||||
# This file is processed by m4 so be careful to quote (`') names
|
||||
# that match m4 reserved words. Also, within ifdef's, arguments
|
||||
# containing commas must be quoted.
|
||||
#
|
||||
# Note: Have to exclude user from most lines so that user.alert
|
||||
# and user.emerg are not included, because old sendmails
|
||||
# will generate them for debugging information. If you
|
||||
# have no 4.2BSD based systems doing network logging, you
|
||||
# can remove all the special cases for "user" logging.
|
||||
|
||||
#*.err;kern.debug;auth.notice;user.none /dev/console
|
||||
kern.debug;user,mail.crit;auth.notice /dev/console
|
||||
daemon,syslog,lpr,news,uucp,cron.err /dev/console
|
||||
|
||||
#*.err;kern.debug;daemon,auth.notice;mail.crit;user.none /var/adm/messages
|
||||
kern.debug;user,mail.crit;auth.notice /var/adm/messages
|
||||
daemon.notice;syslog,news,uucp,cron.err /var/adm/messages
|
||||
|
||||
lpr.debug /var/adm/lpd-errs
|
||||
|
||||
*.alert;kern.err;daemon.err;user.none operator
|
||||
*.alert;user.none root
|
||||
|
||||
*.emerg;user.none *
|
||||
|
||||
# for loghost machines, to have authentication messages (su, login, etc.)
|
||||
# logged to a file, un-comment out the following line and adjust the file name
|
||||
# as appropriate.
|
||||
#
|
||||
# if a non-loghost machine chooses to have such messages
|
||||
# sent to the loghost machine, un-comment out the following line.
|
||||
#
|
||||
#auth.notice ifdef(`LOGHOST', /var/log/authlog, @loghost)
|
||||
|
||||
mail.debug ifdef(`LOGHOST', /var/log/syslog, @loghost)
|
||||
|
||||
# following line for compatibility with old sendmails. they will send
|
||||
# messages with no facility code, which will be turned into "user" messages
|
||||
# by the local syslog daemon. only the "loghost" machine needs the following
|
||||
# line, to cause these old sendmail log messages to be logged in the
|
||||
# mail syslog file.
|
||||
#
|
||||
ifdef(`LOGHOST',
|
||||
user.alert /var/log/syslog
|
||||
)
|
||||
#
|
||||
# non-loghost machines will use the following lines to cause "user"
|
||||
# log messages to be logged locally.
|
||||
#
|
||||
ifdef(`LOGHOST', ,
|
||||
user.err /dev/console
|
||||
user.err /var/adm/messages
|
||||
user.alert `root, operator'
|
||||
user.emerg *
|
||||
)
|
||||
|
||||
# Local2: (bootpd, pppd)
|
||||
local2.debug /dev/console
|
||||
#local2.debug /var/log/local2
|
52
libexec/bootpd/tools/bootpef/bootpef.8
Normal file
52
libexec/bootpd/tools/bootpef/bootpef.8
Normal file
@ -0,0 +1,52 @@
|
||||
.\" bootpef.8
|
||||
.TH BOOTPEF 8 "4 Dec 1993" "MAINTENANCE COMMANDS"
|
||||
.SH NAME
|
||||
bootpef \- BOOTP Extension File compiler
|
||||
.SH SYNOPSIS
|
||||
.LP
|
||||
.B bootpef
|
||||
.RI [ "-c chdir" ]
|
||||
.RI [ "-d debug-level" ]
|
||||
.RI [ "-f config-file" ]
|
||||
.RI [ client-name " [...]]"
|
||||
.SH DESCRIPTION
|
||||
.B bootpef
|
||||
builds the
|
||||
.I Extension Path
|
||||
files described by RFC 1497 (tag 18).
|
||||
If any
|
||||
.I client-name
|
||||
arguments are specified, then
|
||||
.I bootpef
|
||||
compiles the extension files for only those clients.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BI \-c \ chdir\-path
|
||||
Sets the current directory used by
|
||||
.I bootpef
|
||||
while creating extension files. This is useful when the
|
||||
extension file names are specified as relative pathnames, and
|
||||
.I bootpef
|
||||
needs to use the same current directory as the TFTP server
|
||||
(typically /tftpboot).
|
||||
.TP
|
||||
.BI \-d \ debug\-level
|
||||
Sets the
|
||||
.I debug\-level
|
||||
variable that controls the amount of debugging messages generated.
|
||||
For example, -d4 or -d 4 will set the debugging level to 4.
|
||||
.TP
|
||||
.BI \-f \ config\-file
|
||||
Set the name of the config file that specifies the option
|
||||
data to be sent to each client.
|
||||
.SH "SEE ALSO"
|
||||
bootpd(8), tftpd(8)
|
||||
.SH REFERENCES
|
||||
.TP
|
||||
RFC951
|
||||
BOOTSTRAP PROTOCOL (BOOTP)
|
||||
.TP
|
||||
RFC1497
|
||||
BOOTP Vendor Information Extensions
|
||||
|
||||
|
347
libexec/bootpd/tools/bootpef/bootpef.c
Normal file
347
libexec/bootpd/tools/bootpef/bootpef.c
Normal file
@ -0,0 +1,347 @@
|
||||
/************************************************************************
|
||||
Copyright 1988, 1991 by Carnegie Mellon University
|
||||
|
||||
All Rights Reserved
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted, provided
|
||||
that the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation, and that the name of Carnegie Mellon University not be used
|
||||
in advertising or publicity pertaining to distribution of the software
|
||||
without specific, written prior permission.
|
||||
|
||||
CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
|
||||
IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
SOFTWARE.
|
||||
************************************************************************/
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$Id: bootpef.c,v 1.1.1.1 1994/09/10 14:44:54 csgr Exp $";
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* bootpef - BOOTP Extension File generator
|
||||
* Makes an "Extension File" for each host entry that
|
||||
* defines an and Extension File. (See RFC1497, tag 18.)
|
||||
*
|
||||
* HISTORY
|
||||
* See ./Changes
|
||||
*
|
||||
* BUGS
|
||||
* See ./ToDo
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h> /* inet_ntoa */
|
||||
|
||||
#ifndef NO_UNISTD
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#ifndef USE_BFUNCS
|
||||
#include <memory.h>
|
||||
/* Yes, memcpy is OK here (no overlapped copies). */
|
||||
#define bcopy(a,b,c) memcpy(b,a,c)
|
||||
#define bzero(p,l) memset(p,0,l)
|
||||
#define bcmp(a,b,c) memcmp(a,b,c)
|
||||
#endif
|
||||
|
||||
#include "bootp.h"
|
||||
#include "hash.h"
|
||||
#include "hwaddr.h"
|
||||
#include "bootpd.h"
|
||||
#include "dovend.h"
|
||||
#include "readfile.h"
|
||||
#include "report.h"
|
||||
#include "tzone.h"
|
||||
#include "patchlevel.h"
|
||||
|
||||
#define BUFFERSIZE 0x4000
|
||||
|
||||
#ifndef CONFIG_FILE
|
||||
#define CONFIG_FILE "/etc/bootptab"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Externals, forward declarations, and global variables
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
#define P(args) args
|
||||
#else
|
||||
#define P(args) ()
|
||||
#endif
|
||||
|
||||
static void dovend_rfc1048 P((struct bootp *, struct host *, int32));
|
||||
static void mktagfile P((struct host *));
|
||||
static void usage P((void));
|
||||
|
||||
#undef P
|
||||
|
||||
|
||||
/*
|
||||
* General
|
||||
*/
|
||||
|
||||
char *progname;
|
||||
char *chdir_path;
|
||||
int debug = 0; /* Debugging flag (level) */
|
||||
byte *buffer;
|
||||
|
||||
/*
|
||||
* Globals below are associated with the bootp database file (bootptab).
|
||||
*/
|
||||
|
||||
char *bootptab = CONFIG_FILE;
|
||||
|
||||
|
||||
/*
|
||||
* Print "usage" message and exit
|
||||
*/
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: $s [ -c chdir ] [-d level] [-f configfile] [host...]\n");
|
||||
fprintf(stderr, "\t -c n\tset current directory\n");
|
||||
fprintf(stderr, "\t -d n\tset debug level\n");
|
||||
fprintf(stderr, "\t -f n\tconfig file name\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialization such as command-line processing is done and then the
|
||||
* main server loop is started.
|
||||
*/
|
||||
void
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
struct host *hp;
|
||||
char *stmp;
|
||||
int n;
|
||||
|
||||
progname = strrchr(argv[0], '/');
|
||||
if (progname) progname++;
|
||||
else progname = argv[0];
|
||||
|
||||
/* Get work space for making tag 18 files. */
|
||||
buffer = (byte *) malloc(BUFFERSIZE);
|
||||
if (!buffer) {
|
||||
report(LOG_ERR, "malloc failed");
|
||||
exit(1);
|
||||
}
|
||||
/*
|
||||
* Set defaults that might be changed by option switches.
|
||||
*/
|
||||
stmp = NULL;
|
||||
|
||||
/*
|
||||
* Read switches.
|
||||
*/
|
||||
for (argc--, argv++; argc > 0; argc--, argv++) {
|
||||
if (argv[0][0] != '-')
|
||||
break;
|
||||
switch (argv[0][1]) {
|
||||
|
||||
case 'c': /* chdir_path */
|
||||
if (argv[0][2]) {
|
||||
stmp = &(argv[0][2]);
|
||||
} else {
|
||||
argc--;
|
||||
argv++;
|
||||
stmp = argv[0];
|
||||
}
|
||||
if (!stmp || (stmp[0] != '/')) {
|
||||
fprintf(stderr,
|
||||
"bootpd: invalid chdir specification\n");
|
||||
break;
|
||||
}
|
||||
chdir_path = stmp;
|
||||
break;
|
||||
|
||||
case 'd': /* debug */
|
||||
if (argv[0][2]) {
|
||||
stmp = &(argv[0][2]);
|
||||
} else if (argv[1] && argv[1][0] == '-') {
|
||||
/*
|
||||
* Backwards-compatible behavior:
|
||||
* no parameter, so just increment the debug flag.
|
||||
*/
|
||||
debug++;
|
||||
break;
|
||||
} else {
|
||||
argc--;
|
||||
argv++;
|
||||
stmp = argv[0];
|
||||
}
|
||||
if (!stmp || (sscanf(stmp, "%d", &n) != 1) || (n < 0)) {
|
||||
fprintf(stderr,
|
||||
"bootpd: invalid debug level\n");
|
||||
break;
|
||||
}
|
||||
debug = n;
|
||||
break;
|
||||
|
||||
case 'f': /* config file */
|
||||
if (argv[0][2]) {
|
||||
stmp = &(argv[0][2]);
|
||||
} else {
|
||||
argc--;
|
||||
argv++;
|
||||
stmp = argv[0];
|
||||
}
|
||||
bootptab = stmp;
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "bootpd: unknown switch: -%c\n",
|
||||
argv[0][1]);
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the timezone. */
|
||||
tzone_init();
|
||||
|
||||
/* Allocate hash tables. */
|
||||
rdtab_init();
|
||||
|
||||
/*
|
||||
* Read the bootptab file.
|
||||
*/
|
||||
readtab(1); /* force read */
|
||||
|
||||
/* Set the cwd (i.e. to /tftpboot) */
|
||||
if (chdir_path) {
|
||||
if (chdir(chdir_path) < 0)
|
||||
report(LOG_ERR, "%s: chdir failed", chdir_path);
|
||||
}
|
||||
/* If there are host names on the command line, do only those. */
|
||||
if (argc > 0) {
|
||||
unsigned int tlen, hashcode;
|
||||
|
||||
while (argc) {
|
||||
tlen = strlen(argv[0]);
|
||||
hashcode = hash_HashFunction((u_char *)argv[0], tlen);
|
||||
hp = (struct host *) hash_Lookup(nmhashtable,
|
||||
hashcode,
|
||||
nmcmp, argv[0]);
|
||||
if (!hp) {
|
||||
printf("%s: no matching entry\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if (!hp->flags.exten_file) {
|
||||
printf("%s: no extension file\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
mktagfile(hp);
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
/* No host names specified. Do them all. */
|
||||
hp = (struct host *) hash_FirstEntry(nmhashtable);
|
||||
while (hp != NULL) {
|
||||
mktagfile(hp);
|
||||
hp = (struct host *) hash_NextEntry(nmhashtable);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Make a "TAG 18" file for this host.
|
||||
* (Insert the RFC1497 options.)
|
||||
*/
|
||||
|
||||
static void
|
||||
mktagfile(hp)
|
||||
struct host *hp;
|
||||
{
|
||||
FILE *fp;
|
||||
int bytesleft, len;
|
||||
byte *vp;
|
||||
char *tmpstr;
|
||||
|
||||
if (!hp->flags.exten_file)
|
||||
return;
|
||||
|
||||
vp = buffer;
|
||||
bytesleft = BUFFERSIZE;
|
||||
bcopy(vm_rfc1048, vp, 4); /* Copy in the magic cookie */
|
||||
vp += 4;
|
||||
bytesleft -= 4;
|
||||
|
||||
/*
|
||||
* The "extension file" options are appended by the following
|
||||
* function (which is shared with bootpd.c).
|
||||
*/
|
||||
len = dovend_rfc1497(hp, vp, bytesleft);
|
||||
vp += len;
|
||||
bytesleft -= len;
|
||||
|
||||
if (bytesleft < 1) {
|
||||
report(LOG_ERR, "%s: too much option data",
|
||||
hp->exten_file->string);
|
||||
return;
|
||||
}
|
||||
*vp++ = TAG_END;
|
||||
bytesleft--;
|
||||
|
||||
/* Write the buffer to the extension file. */
|
||||
printf("Updating \"%s\"\n", hp->exten_file->string);
|
||||
if ((fp = fopen(hp->exten_file->string, "w")) == NULL) {
|
||||
report(LOG_ERR, "error opening \"%s\": %s",
|
||||
hp->exten_file->string, get_errmsg());
|
||||
return;
|
||||
}
|
||||
len = vp - buffer;
|
||||
if (len != fwrite(buffer, 1, len, fp)) {
|
||||
report(LOG_ERR, "write failed on \"%s\" : %s",
|
||||
hp->exten_file->string, get_errmsg());
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
} /* dovend_rfc1048 */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-argdecl-indent: 4
|
||||
* c-continued-statement-offset: 4
|
||||
* c-continued-brace-offset: -4
|
||||
* c-label-offset: -4
|
||||
* c-brace-offset: 0
|
||||
* End:
|
||||
*/
|
74
libexec/bootpd/tools/bootptest/bootptest.8
Normal file
74
libexec/bootpd/tools/bootptest/bootptest.8
Normal file
@ -0,0 +1,74 @@
|
||||
.\" bootptest.8
|
||||
.TH BOOTPTEST 8 "10 June 1993" "MAINTENANCE COMMANDS"
|
||||
.SH NAME
|
||||
bootptest \- send BOOTP queries and print responses
|
||||
.SH SYNOPSIS
|
||||
.LP
|
||||
.B bootptest
|
||||
[
|
||||
.B \-f
|
||||
.I bootfile
|
||||
]
|
||||
[
|
||||
.B \-h
|
||||
]
|
||||
[
|
||||
.B \-m
|
||||
.I magic_number
|
||||
]
|
||||
.I server\-name
|
||||
.RI [ template-file ]
|
||||
.SH DESCRIPTION
|
||||
.B bootptest
|
||||
sends BOOTP requests to the host specified as
|
||||
.I server\-name
|
||||
at one\-second intervals until either a response is received,
|
||||
or until ten requests have gone unanswered.
|
||||
After a response is received,
|
||||
.B bootptest
|
||||
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
|
||||
may be specified, in which case
|
||||
.B bootptest
|
||||
uses the (binary) contents of this file to initialize the
|
||||
.I options
|
||||
area of the request packet.
|
||||
.SH CREDITS
|
||||
.LP
|
||||
The bootptest program is a combination of original and derived works.
|
||||
The main program module (bootptest.c) is original work by
|
||||
Gordon W. Ross <gwr@mc.com>.
|
||||
The packet printing module (print-bootp.c) is a slightly modified
|
||||
version of a file from the BSD tcpdump program.
|
||||
.LP
|
||||
This program includes software developed by the University of
|
||||
California, Lawrence Berkeley Laboratory and its contributors.
|
||||
(See the copyright notice in print-bootp.c)
|
||||
.SH "SEE ALSO"
|
||||
.LP
|
||||
bootpd(8)
|
||||
.SH REFERENCES
|
||||
.TP
|
||||
RFC951
|
||||
BOOTSTRAP PROTOCOL (BOOTP)
|
||||
.TP
|
||||
RFC1048
|
||||
BOOTP Vendor Information Extensions
|
500
libexec/bootpd/tools/bootptest/bootptest.c
Normal file
500
libexec/bootpd/tools/bootptest/bootptest.c
Normal file
@ -0,0 +1,500 @@
|
||||
/*
|
||||
* bootptest.c - Test out a bootp server.
|
||||
*
|
||||
* This simple program was put together from pieces taken from
|
||||
* 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 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. Gordon W. Ross
|
||||
*
|
||||
* Boilerplate:
|
||||
*
|
||||
* This program includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory and its contributors.
|
||||
* (See the copyright notice in print-bootp.c)
|
||||
*
|
||||
* The remainder of this program is public domain. You may do
|
||||
* whatever you like with it except claim that you wrote it.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* HISTORY:
|
||||
*
|
||||
* 12/02/93 Released version 1.4 (with bootp-2.3.2)
|
||||
* 11/05/93 Released version 1.3
|
||||
* 10/14/93 Released version 1.2
|
||||
* 10/11/93 Released version 1.1
|
||||
* 09/28/93 Released version 1.0
|
||||
* 09/93 Original developed by Gordon W. Ross <gwr@mc.com>
|
||||
*/
|
||||
|
||||
char *usage = "bootptest [-h] server-name [vendor-data-template-file]";
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h> /* inet_ntoa */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <netdb.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "bootp.h"
|
||||
#include "bootptest.h"
|
||||
#include "getif.h"
|
||||
#include "patchlevel.h"
|
||||
|
||||
#define LOG_ERR 1
|
||||
#define BUFLEN 1024
|
||||
#define WAITSECS 1
|
||||
#define MAXWAIT 10
|
||||
|
||||
int vflag = 1;
|
||||
int tflag = 0;
|
||||
int thiszone;
|
||||
char *progname;
|
||||
unsigned char *packetp;
|
||||
unsigned char *snapend;
|
||||
int snaplen;
|
||||
|
||||
|
||||
/*
|
||||
* IP port numbers for client and server obtained from /etc/services
|
||||
*/
|
||||
|
||||
u_short bootps_port, bootpc_port;
|
||||
|
||||
|
||||
/*
|
||||
* Internet socket and interface config structures
|
||||
*/
|
||||
|
||||
struct sockaddr_in sin_server; /* where to send requests */
|
||||
struct sockaddr_in sin_client; /* for bind and listen */
|
||||
struct sockaddr_in sin_from; /* Packet source */
|
||||
u_char eaddr[16]; /* Ethernet address */
|
||||
|
||||
/*
|
||||
* General
|
||||
*/
|
||||
|
||||
int debug = 1; /* Debugging flag (level) */
|
||||
char hostname[64];
|
||||
char *sndbuf; /* Send packet buffer */
|
||||
char *rcvbuf; /* Receive packet buffer */
|
||||
|
||||
/*
|
||||
* Vendor magic cookies for CMU and RFC1048
|
||||
*/
|
||||
|
||||
unsigned char vm_cmu[4] = VM_CMU;
|
||||
unsigned char vm_rfc1048[4] = VM_RFC1048;
|
||||
short secs; /* How long client has waited */
|
||||
|
||||
char *get_errmsg();
|
||||
extern void bootp_print();
|
||||
|
||||
/*
|
||||
* Initialization such as command-line processing is done, then
|
||||
* the receiver loop is started. Die when interrupted.
|
||||
*/
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
struct bootp *bp;
|
||||
struct servent *sep;
|
||||
struct hostent *hep;
|
||||
|
||||
char *servername = NULL;
|
||||
char *vendor_file = NULL;
|
||||
char *bp_file = NULL;
|
||||
int32 server_addr; /* inet addr, network order */
|
||||
int s; /* Socket file descriptor */
|
||||
int n, tolen, fromlen, recvcnt;
|
||||
int use_hwa = 0;
|
||||
int32 vend_magic;
|
||||
int32 xid;
|
||||
|
||||
progname = strrchr(argv[0], '/');
|
||||
if (progname)
|
||||
progname++;
|
||||
else
|
||||
progname = argv[0];
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (debug)
|
||||
printf("%s: version %s.%d\n", progname, VERSION, PATCHLEVEL);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
rcvbuf = malloc(BUFLEN);
|
||||
if (!sndbuf || !rcvbuf) {
|
||||
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] != '-')
|
||||
break;
|
||||
switch (argv[0][1]) {
|
||||
|
||||
case 'f': /* File name to reqest. */
|
||||
if (argc < 2)
|
||||
goto error;
|
||||
argc--; argv++;
|
||||
bp_file = *argv;
|
||||
break;
|
||||
|
||||
case 'h': /* Use hardware address. */
|
||||
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);
|
||||
exit(1);
|
||||
|
||||
}
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
/* Get server name (or address) for query. */
|
||||
if (argc > 0) {
|
||||
servername = *argv;
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
/* Get optional vendor-data-template-file. */
|
||||
if (argc > 0) {
|
||||
vendor_file = *argv;
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
if (!servername) {
|
||||
printf("missing server name.\n");
|
||||
puts(usage);
|
||||
exit(1);
|
||||
}
|
||||
/*
|
||||
* Create a socket.
|
||||
*/
|
||||
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
/*
|
||||
* Get server's listening port number
|
||||
*/
|
||||
sep = getservbyname("bootps", "udp");
|
||||
if (sep) {
|
||||
bootps_port = ntohs((u_short) sep->s_port);
|
||||
} else {
|
||||
fprintf(stderr, "udp/bootps: unknown service -- using port %d\n",
|
||||
IPPORT_BOOTPS);
|
||||
bootps_port = (u_short) IPPORT_BOOTPS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up server socket address (for send)
|
||||
*/
|
||||
if (servername) {
|
||||
if (isdigit(servername[0]))
|
||||
server_addr = inet_addr(servername);
|
||||
else {
|
||||
hep = gethostbyname(servername);
|
||||
if (!hep) {
|
||||
fprintf(stderr, "%s: unknown host\n", servername);
|
||||
exit(1);
|
||||
}
|
||||
bcopy(hep->h_addr, &server_addr, sizeof(server_addr));
|
||||
}
|
||||
} else {
|
||||
/* Get broadcast address */
|
||||
/* XXX - not yet */
|
||||
server_addr = INADDR_ANY;
|
||||
}
|
||||
sin_server.sin_family = AF_INET;
|
||||
sin_server.sin_port = htons(bootps_port);
|
||||
sin_server.sin_addr.s_addr = server_addr;
|
||||
|
||||
/*
|
||||
* Get client's listening port number
|
||||
*/
|
||||
sep = getservbyname("bootpc", "udp");
|
||||
if (sep) {
|
||||
bootpc_port = ntohs(sep->s_port);
|
||||
} else {
|
||||
fprintf(stderr, "udp/bootpc: unknown service -- using port %d\n",
|
||||
IPPORT_BOOTPC);
|
||||
bootpc_port = (u_short) IPPORT_BOOTPC;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up client socket address (for listen)
|
||||
*/
|
||||
sin_client.sin_family = AF_INET;
|
||||
sin_client.sin_port = htons(bootpc_port);
|
||||
sin_client.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
/*
|
||||
* Bind client socket to BOOTPC port.
|
||||
*/
|
||||
if (bind(s, (struct sockaddr *) &sin_client, sizeof(sin_client)) < 0) {
|
||||
perror("bind BOOTPC port");
|
||||
if (errno == EACCES)
|
||||
fprintf(stderr, "You need to run this as root\n");
|
||||
exit(1);
|
||||
}
|
||||
/*
|
||||
* Build a request.
|
||||
*/
|
||||
bp = (struct bootp *) sndbuf;
|
||||
bzero(bp, sizeof(*bp));
|
||||
bp->bp_op = BOOTREQUEST;
|
||||
xid = (int32) getpid();
|
||||
bp->bp_xid = (u_int32) htonl(xid);
|
||||
if (bp_file)
|
||||
strncpy(bp->bp_file, bp_file, BP_FILE_LEN);
|
||||
|
||||
/*
|
||||
* Fill in the hardware address (or client IP address)
|
||||
*/
|
||||
if (use_hwa) {
|
||||
struct ifreq *ifr;
|
||||
|
||||
ifr = getif(s, &sin_server.sin_addr);
|
||||
if (!ifr) {
|
||||
printf("No interface for %s\n", servername);
|
||||
exit(1);
|
||||
}
|
||||
if (getether(ifr->ifr_name, eaddr)) {
|
||||
printf("Can not get ether addr for %s\n", ifr->ifr_name);
|
||||
exit(1);
|
||||
}
|
||||
/* Copy Ethernet address into request packet. */
|
||||
bp->bp_htype = 1;
|
||||
bp->bp_hlen = 6;
|
||||
bcopy(eaddr, bp->bp_chaddr, bp->bp_hlen);
|
||||
} else {
|
||||
/* Fill in the client IP address. */
|
||||
gethostname(hostname, sizeof(hostname));
|
||||
hep = gethostbyname(hostname);
|
||||
if (!hep) {
|
||||
printf("Can not get my IP address\n");
|
||||
exit(1);
|
||||
}
|
||||
bcopy(hep->h_addr, &bp->bp_ciaddr, hep->h_length);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy in the default vendor data.
|
||||
*/
|
||||
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.
|
||||
* This also determines the size of the packet.
|
||||
*/
|
||||
snaplen = sizeof(*bp);
|
||||
if (vendor_file) {
|
||||
int fd = open(vendor_file, 0);
|
||||
if (fd < 0) {
|
||||
perror(vendor_file);
|
||||
exit(1);
|
||||
}
|
||||
/* Compute actual space for options. */
|
||||
n = BUFLEN - sizeof(*bp) + BP_VEND_LEN;
|
||||
n = read(fd, bp->bp_vend, n);
|
||||
close(fd);
|
||||
if (n < 0) {
|
||||
perror(vendor_file);
|
||||
exit(1);
|
||||
}
|
||||
printf("read %d bytes of vendor template\n", n);
|
||||
if (n > BP_VEND_LEN) {
|
||||
printf("warning: extended options in use (len > %d)\n",
|
||||
BP_VEND_LEN);
|
||||
snaplen += (n - BP_VEND_LEN);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Set globals needed by print_bootp
|
||||
* (called by send_request)
|
||||
*/
|
||||
packetp = (unsigned char *) eaddr;
|
||||
snapend = (unsigned char *) sndbuf + snaplen;
|
||||
|
||||
/* Send a request once per second while waiting for replies. */
|
||||
recvcnt = 0;
|
||||
bp->bp_secs = secs = 0;
|
||||
send_request(s);
|
||||
while (1) {
|
||||
struct timeval tv;
|
||||
int readfds;
|
||||
|
||||
tv.tv_sec = WAITSECS;
|
||||
tv.tv_usec = 0L;
|
||||
readfds = (1 << s);
|
||||
n = select(s + 1, (fd_set *) & readfds, NULL, NULL, &tv);
|
||||
if (n < 0) {
|
||||
perror("select");
|
||||
break;
|
||||
}
|
||||
if (n == 0) {
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
if (recvcnt > 0)
|
||||
exit(0);
|
||||
secs += WAITSECS;
|
||||
if (secs > MAXWAIT)
|
||||
break;
|
||||
bp->bp_secs = htons(secs);
|
||||
send_request(s);
|
||||
continue;
|
||||
}
|
||||
fromlen = sizeof(sin_from);
|
||||
n = recvfrom(s, rcvbuf, BUFLEN, 0,
|
||||
(struct sockaddr *) &sin_from, &fromlen);
|
||||
if (n <= 0) {
|
||||
continue;
|
||||
}
|
||||
if (n < sizeof(struct bootp)) {
|
||||
printf("received short packet\n");
|
||||
continue;
|
||||
}
|
||||
recvcnt++;
|
||||
|
||||
/* Print the received packet. */
|
||||
printf("Recvd from %s", inet_ntoa(sin_from.sin_addr));
|
||||
/* set globals needed by bootp_print() */
|
||||
snaplen = n;
|
||||
snapend = (unsigned char *) rcvbuf + snaplen;
|
||||
bootp_print(rcvbuf, n, sin_from.sin_port, 0);
|
||||
putchar('\n');
|
||||
/*
|
||||
* This no longer exits immediately after receiving
|
||||
* one response because it is useful to know if the
|
||||
* client might get multiple responses. This code
|
||||
* will now listen for one second after a response.
|
||||
*/
|
||||
}
|
||||
fprintf(stderr, "no response from %s\n", servername);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
send_request(s)
|
||||
int s;
|
||||
{
|
||||
/* Print the request packet. */
|
||||
printf("Sending to %s", inet_ntoa(sin_server.sin_addr));
|
||||
bootp_print(sndbuf, snaplen, sin_from.sin_port, 0);
|
||||
putchar('\n');
|
||||
|
||||
/* Send the request packet. */
|
||||
if (sendto(s, sndbuf, snaplen, 0,
|
||||
(struct sockaddr *) &sin_server,
|
||||
sizeof(sin_server)) < 0)
|
||||
{
|
||||
perror("sendto server");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print out a filename (or other ascii string).
|
||||
* Return true if truncated.
|
||||
*/
|
||||
int
|
||||
printfn(s, ep)
|
||||
register u_char *s, *ep;
|
||||
{
|
||||
register u_char c;
|
||||
|
||||
putchar('"');
|
||||
while (c = *s++) {
|
||||
if (s > ep) {
|
||||
putchar('"');
|
||||
return (1);
|
||||
}
|
||||
if (!isascii(c)) {
|
||||
c = toascii(c);
|
||||
putchar('M');
|
||||
putchar('-');
|
||||
}
|
||||
if (!isprint(c)) {
|
||||
c ^= 0x40; /* DEL to ?, others to alpha */
|
||||
putchar('^');
|
||||
}
|
||||
putchar(c);
|
||||
}
|
||||
putchar('"');
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an IP addr to a string.
|
||||
* (like inet_ntoa, but ina is a pointer)
|
||||
*/
|
||||
char *
|
||||
ipaddr_string(ina)
|
||||
struct in_addr *ina;
|
||||
{
|
||||
static char b[24];
|
||||
u_char *p;
|
||||
|
||||
p = (u_char *) ina;
|
||||
sprintf(b, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
|
||||
return (b);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-argdecl-indent: 4
|
||||
* c-continued-statement-offset: 4
|
||||
* c-continued-brace-offset: -4
|
||||
* c-label-offset: -4
|
||||
* c-brace-offset: 0
|
||||
* End:
|
||||
*/
|
30
libexec/bootpd/tools/bootptest/bootptest.h
Normal file
30
libexec/bootpd/tools/bootptest/bootptest.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* bootptest.h */
|
||||
/*
|
||||
* Hacks for sharing print-bootp.c between tcpdump and bootptest.
|
||||
*/
|
||||
#define ESRC(p) (p)
|
||||
#define EDST(p) (p)
|
||||
|
||||
#ifndef USE_BFUNCS
|
||||
/* Use mem/str functions */
|
||||
/* There are no overlapped copies, so memcpy is OK. */
|
||||
#define bcopy(a,b,c) memcpy(b,a,c)
|
||||
#define bzero(p,l) memset(p,0,l)
|
||||
#define bcmp(a,b,c) memcmp(a,b,c)
|
||||
#endif
|
||||
|
||||
extern int vflag; /* verbose flag */
|
||||
|
||||
/* global pointers to beginning and end of current packet (during printing) */
|
||||
extern unsigned char *packetp;
|
||||
extern unsigned char *snapend;
|
||||
|
||||
#ifdef __STDC__
|
||||
#define P(args) args
|
||||
#else
|
||||
#define P(args) ()
|
||||
#endif
|
||||
|
||||
extern char *ipaddr_string P((struct in_addr *));
|
||||
|
||||
#undef P
|
493
libexec/bootpd/tools/bootptest/print-bootp.c
Normal file
493
libexec/bootpd/tools/bootptest/print-bootp.c
Normal file
@ -0,0 +1,493 @@
|
||||
/*
|
||||
* Copyright (c) 1988-1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the University of California,
|
||||
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Format and print bootp packets.
|
||||
*
|
||||
* This file was copied from tcpdump-2.1.1 and modified.
|
||||
* There is an e-mail list for tcpdump: <tcpdump@ee.lbl.gov>
|
||||
*/
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$Id: print-bootp.c,v 1.1.1.1 1994/09/10 14:44:55 csgr Exp $";
|
||||
/* 93/10/10 <gwr@mc.com> New data-driven option print routine. */
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "bootp.h"
|
||||
#include "bootptest.h"
|
||||
|
||||
/* These decode the vendor data. */
|
||||
static void rfc1048_print();
|
||||
static void cmu_print();
|
||||
static void other_print();
|
||||
static void dump_hex();
|
||||
|
||||
/*
|
||||
* Print bootp requests
|
||||
*/
|
||||
void
|
||||
bootp_print(bp, length, sport, dport)
|
||||
struct bootp *bp;
|
||||
int length;
|
||||
u_short sport, dport;
|
||||
{
|
||||
static char tstr[] = " [|bootp]";
|
||||
static unsigned char vm_cmu[4] = VM_CMU;
|
||||
static unsigned char vm_rfc1048[4] = VM_RFC1048;
|
||||
u_char *ep;
|
||||
int vdlen;
|
||||
|
||||
#define TCHECK(var, l) if ((u_char *)&(var) > ep - l) goto trunc
|
||||
|
||||
/* Note funny sized packets */
|
||||
if (length != sizeof(struct bootp))
|
||||
(void) printf(" [len=%d]", length);
|
||||
|
||||
/* 'ep' points to the end of avaible data. */
|
||||
ep = (u_char *) snapend;
|
||||
|
||||
switch (bp->bp_op) {
|
||||
|
||||
case BOOTREQUEST:
|
||||
/* Usually, a request goes from a client to a server */
|
||||
if (sport != IPPORT_BOOTPC || dport != IPPORT_BOOTPS)
|
||||
printf(" (request)");
|
||||
break;
|
||||
|
||||
case BOOTREPLY:
|
||||
/* Usually, a reply goes from a server to a client */
|
||||
if (sport != IPPORT_BOOTPS || dport != IPPORT_BOOTPC)
|
||||
printf(" (reply)");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf(" bootp-#%d", bp->bp_op);
|
||||
}
|
||||
|
||||
/* The usual hardware address type is 1 (10Mb Ethernet) */
|
||||
if (bp->bp_htype != 1)
|
||||
printf(" htype:%d", bp->bp_htype);
|
||||
|
||||
/* The usual length for 10Mb Ethernet address is 6 bytes */
|
||||
if (bp->bp_hlen != 6)
|
||||
printf(" hlen:%d", bp->bp_hlen);
|
||||
|
||||
/* Client's Hardware address */
|
||||
if (bp->bp_hlen) {
|
||||
register struct ether_header *eh;
|
||||
register char *e;
|
||||
|
||||
TCHECK(bp->bp_chaddr[0], 6);
|
||||
eh = (struct ether_header *) packetp;
|
||||
if (bp->bp_op == BOOTREQUEST)
|
||||
e = (char *) ESRC(eh);
|
||||
else if (bp->bp_op == BOOTREPLY)
|
||||
e = (char *) EDST(eh);
|
||||
else
|
||||
e = 0;
|
||||
if (e == 0 || bcmp((char *) bp->bp_chaddr, e, 6))
|
||||
dump_hex(bp->bp_chaddr, bp->bp_hlen);
|
||||
}
|
||||
/* Only print interesting fields */
|
||||
if (bp->bp_hops)
|
||||
printf(" hops:%d", bp->bp_hops);
|
||||
|
||||
if (bp->bp_xid)
|
||||
printf(" xid:%d", ntohl(bp->bp_xid));
|
||||
|
||||
if (bp->bp_secs)
|
||||
printf(" secs:%d", ntohs(bp->bp_secs));
|
||||
|
||||
/* Client's ip address */
|
||||
TCHECK(bp->bp_ciaddr, sizeof(bp->bp_ciaddr));
|
||||
if (bp->bp_ciaddr.s_addr)
|
||||
printf(" C:%s", ipaddr_string(&bp->bp_ciaddr));
|
||||
|
||||
/* 'your' ip address (bootp client) */
|
||||
TCHECK(bp->bp_yiaddr, sizeof(bp->bp_yiaddr));
|
||||
if (bp->bp_yiaddr.s_addr)
|
||||
printf(" Y:%s", ipaddr_string(&bp->bp_yiaddr));
|
||||
|
||||
/* Server's ip address */
|
||||
TCHECK(bp->bp_siaddr, sizeof(bp->bp_siaddr));
|
||||
if (bp->bp_siaddr.s_addr)
|
||||
printf(" S:%s", ipaddr_string(&bp->bp_siaddr));
|
||||
|
||||
/* Gateway's ip address */
|
||||
TCHECK(bp->bp_giaddr, sizeof(bp->bp_giaddr));
|
||||
if (bp->bp_giaddr.s_addr)
|
||||
printf(" G:%s", ipaddr_string(&bp->bp_giaddr));
|
||||
|
||||
TCHECK(bp->bp_sname[0], sizeof(bp->bp_sname));
|
||||
if (*bp->bp_sname) {
|
||||
printf(" sname:");
|
||||
if (printfn(bp->bp_sname, ep)) {
|
||||
fputs(tstr + 1, stdout);
|
||||
return;
|
||||
}
|
||||
}
|
||||
TCHECK(bp->bp_file[0], sizeof(bp->bp_file));
|
||||
if (*bp->bp_file) {
|
||||
printf(" file:");
|
||||
if (printfn(bp->bp_file, ep)) {
|
||||
fputs(tstr + 1, stdout);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Don't try to decode the vendor buffer unless we're verbose */
|
||||
if (vflag <= 0)
|
||||
return;
|
||||
|
||||
vdlen = sizeof(bp->bp_vend);
|
||||
/* Vendor data can extend to the end of the packet. */
|
||||
if (vdlen < (ep - bp->bp_vend))
|
||||
vdlen = (ep - bp->bp_vend);
|
||||
|
||||
TCHECK(bp->bp_vend[0], vdlen);
|
||||
printf(" vend");
|
||||
if (!bcmp(bp->bp_vend, vm_rfc1048, sizeof(u_int32)))
|
||||
rfc1048_print(bp->bp_vend, vdlen);
|
||||
else if (!bcmp(bp->bp_vend, vm_cmu, sizeof(u_int32)))
|
||||
cmu_print(bp->bp_vend, vdlen);
|
||||
else
|
||||
other_print(bp->bp_vend, vdlen);
|
||||
|
||||
return;
|
||||
trunc:
|
||||
fputs(tstr, stdout);
|
||||
#undef TCHECK
|
||||
}
|
||||
|
||||
/*
|
||||
* Option description data follows.
|
||||
* These are decribed in: RFC-1048, RFC-1395, RFC-1497, RFC-1533
|
||||
*
|
||||
* The first char of each option string encodes the data format:
|
||||
* ?: unknown
|
||||
* a: ASCII
|
||||
* b: byte (8-bit)
|
||||
* i: inet address
|
||||
* l: int32
|
||||
* s: short (16-bit)
|
||||
*/
|
||||
char *
|
||||
rfc1048_opts[] = {
|
||||
/* Originally from RFC-1048: */
|
||||
"?PAD", /* 0: Padding - special, no data. */
|
||||
"iSM", /* 1: subnet mask (RFC950)*/
|
||||
"lTZ", /* 2: time offset, seconds from UTC */
|
||||
"iGW", /* 3: gateways (or routers) */
|
||||
"iTS", /* 4: time servers (RFC868) */
|
||||
"iINS", /* 5: IEN name servers (IEN116) */
|
||||
"iDNS", /* 6: domain name servers (RFC1035)(1034?) */
|
||||
"iLOG", /* 7: MIT log servers */
|
||||
"iCS", /* 8: cookie servers (RFC865) */
|
||||
"iLPR", /* 9: lpr server (RFC1179) */
|
||||
"iIPS", /* 10: impress servers (Imagen) */
|
||||
"iRLP", /* 11: resource location servers (RFC887) */
|
||||
"aHN", /* 12: host name (ASCII) */
|
||||
"sBFS", /* 13: boot file size (in 512 byte blocks) */
|
||||
|
||||
/* Added by RFC-1395: */
|
||||
"aDUMP", /* 14: Merit Dump File */
|
||||
"aDNAM", /* 15: Domain Name (for DNS) */
|
||||
"iSWAP", /* 16: Swap Server */
|
||||
"aROOT", /* 17: Root Path */
|
||||
|
||||
/* Added by RFC-1497: */
|
||||
"aEXTF", /* 18: Extensions Path (more options) */
|
||||
|
||||
/* Added by RFC-1533: (many, many options...) */
|
||||
#if 1 /* These might not be worth recognizing by name. */
|
||||
|
||||
/* IP Layer Parameters, per-host (RFC-1533, sect. 4) */
|
||||
"bIP-forward", /* 19: IP Forwarding flag */
|
||||
"bIP-srcroute", /* 20: IP Source Routing Enable flag */
|
||||
"iIP-filters", /* 21: IP Policy Filter (addr pairs) */
|
||||
"sIP-maxudp", /* 22: IP Max-UDP reassembly size */
|
||||
"bIP-ttlive", /* 23: IP Time to Live */
|
||||
"lIP-pmtuage", /* 24: IP Path MTU aging timeout */
|
||||
"sIP-pmtutab", /* 25: IP Path MTU plateau table */
|
||||
|
||||
/* IP parameters, per-interface (RFC-1533, sect. 5) */
|
||||
"sIP-mtu-sz", /* 26: IP MTU size */
|
||||
"bIP-mtu-sl", /* 27: IP MTU all subnets local */
|
||||
"bIP-bcast1", /* 28: IP Broadcast Addr ones flag */
|
||||
"bIP-mask-d", /* 29: IP do mask discovery */
|
||||
"bIP-mask-s", /* 30: IP do mask supplier */
|
||||
"bIP-rt-dsc", /* 31: IP do router discovery */
|
||||
"iIP-rt-sa", /* 32: IP router solicitation addr */
|
||||
"iIP-routes", /* 33: IP static routes (dst,router) */
|
||||
|
||||
/* Link Layer parameters, per-interface (RFC-1533, sect. 6) */
|
||||
"bLL-trailer", /* 34: do tralier encapsulation */
|
||||
"lLL-arp-tmo", /* 35: ARP cache timeout */
|
||||
"bLL-ether2", /* 36: Ethernet version 2 (IEEE 802.3) */
|
||||
|
||||
/* TCP parameters (RFC-1533, sect. 7) */
|
||||
"bTCP-def-ttl", /* 37: default time to live */
|
||||
"lTCP-KA-tmo", /* 38: keepalive time interval */
|
||||
"bTCP-KA-junk", /* 39: keepalive sends extra junk */
|
||||
|
||||
/* Application and Service Parameters (RFC-1533, sect. 8) */
|
||||
"aNISDOM", /* 40: NIS Domain (Sun YP) */
|
||||
"iNISSRV", /* 41: NIS Servers */
|
||||
"iNTPSRV", /* 42: NTP (time) Servers (RFC 1129) */
|
||||
"?VSINFO", /* 43: Vendor Specific Info (encapsulated) */
|
||||
"iNBiosNS", /* 44: NetBIOS Name Server (RFC-1001,1..2) */
|
||||
"iNBiosDD", /* 45: NetBIOS Datagram Dist. Server. */
|
||||
"bNBiosNT", /* 46: NetBIOS Note Type */
|
||||
"?NBiosS", /* 47: NetBIOS Scope */
|
||||
"iXW-FS", /* 48: X Window System Font Servers */
|
||||
"iXW-DM", /* 49: X Window System Display Managers */
|
||||
|
||||
/* DHCP extensions (RFC-1533, sect. 9) */
|
||||
#endif
|
||||
};
|
||||
#define KNOWN_OPTIONS (sizeof(rfc1048_opts) / sizeof(rfc1048_opts[0]))
|
||||
|
||||
static void print_string();
|
||||
|
||||
static void
|
||||
rfc1048_print(bp, length)
|
||||
register u_char *bp;
|
||||
int length;
|
||||
{
|
||||
u_char tag;
|
||||
u_char *ep;
|
||||
register int len, j;
|
||||
u_int32 ul;
|
||||
u_short us;
|
||||
struct in_addr ia;
|
||||
char *optstr;
|
||||
|
||||
printf("-rfc1395");
|
||||
|
||||
/* Step over magic cookie */
|
||||
bp += sizeof(int32);
|
||||
/* Setup end pointer */
|
||||
ep = bp + length;
|
||||
while (bp < ep) {
|
||||
tag = *bp++;
|
||||
/* Check for tags with no data first. */
|
||||
if (tag == TAG_PAD)
|
||||
continue;
|
||||
if (tag == TAG_END)
|
||||
return;
|
||||
if (tag < KNOWN_OPTIONS) {
|
||||
optstr = rfc1048_opts[tag];
|
||||
printf(" %s:", optstr + 1);
|
||||
} else {
|
||||
printf(" T%d:", tag);
|
||||
optstr = "?";
|
||||
}
|
||||
/* Now scan the length byte. */
|
||||
len = *bp++;
|
||||
if (bp + len > ep) {
|
||||
/* truncated option */
|
||||
printf(" |(%d>%d)", len, ep - bp);
|
||||
return;
|
||||
}
|
||||
/* Print the option value(s). */
|
||||
switch (optstr[0]) {
|
||||
|
||||
case 'a': /* ASCII string */
|
||||
printfn(bp, bp + len);
|
||||
bp += len;
|
||||
len = 0;
|
||||
break;
|
||||
|
||||
case 's': /* Word formats */
|
||||
while (len >= 2) {
|
||||
bcopy((char *) bp, (char *) &us, 2);
|
||||
printf("%d", ntohs(us));
|
||||
bp += 2;
|
||||
len -= 2;
|
||||
if (len) printf(",");
|
||||
}
|
||||
if (len) printf("(junk=%d)", len);
|
||||
break;
|
||||
|
||||
case 'l': /* Long words */
|
||||
while (len >= 4) {
|
||||
bcopy((char *) bp, (char *) &ul, 4);
|
||||
printf("%d", ntohl(ul));
|
||||
bp += 4;
|
||||
len -= 4;
|
||||
if (len) printf(",");
|
||||
}
|
||||
if (len) printf("(junk=%d)", len);
|
||||
break;
|
||||
|
||||
case 'i': /* INET addresses */
|
||||
while (len >= 4) {
|
||||
bcopy((char *) bp, (char *) &ia, 4);
|
||||
printf("%s", ipaddr_string(&ia));
|
||||
bp += 4;
|
||||
len -= 4;
|
||||
if (len) printf(",");
|
||||
}
|
||||
if (len) printf("(junk=%d)", len);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
default:
|
||||
break;
|
||||
|
||||
} /* switch */
|
||||
|
||||
/* Print as characters, if appropriate. */
|
||||
if (len) {
|
||||
dump_hex(bp, len);
|
||||
if (isascii(*bp) && isprint(*bp)) {
|
||||
printf("(");
|
||||
printfn(bp, bp + len);
|
||||
printf(")");
|
||||
}
|
||||
bp += len;
|
||||
len = 0;
|
||||
}
|
||||
} /* while bp < ep */
|
||||
}
|
||||
|
||||
static void
|
||||
cmu_print(bp, length)
|
||||
register u_char *bp;
|
||||
int length;
|
||||
{
|
||||
struct cmu_vend *v;
|
||||
u_char *ep;
|
||||
|
||||
printf("-cmu");
|
||||
|
||||
v = (struct cmu_vend *) bp;
|
||||
if (length < sizeof(*v)) {
|
||||
printf(" |L=%d", length);
|
||||
return;
|
||||
}
|
||||
/* Setup end pointer */
|
||||
ep = bp + length;
|
||||
|
||||
/* Subnet mask */
|
||||
if (v->v_flags & VF_SMASK) {
|
||||
printf(" SM:%s", ipaddr_string(&v->v_smask));
|
||||
}
|
||||
/* Default gateway */
|
||||
if (v->v_dgate.s_addr)
|
||||
printf(" GW:%s", ipaddr_string(&v->v_dgate));
|
||||
|
||||
/* Domain name servers */
|
||||
if (v->v_dns1.s_addr)
|
||||
printf(" DNS1:%s", ipaddr_string(&v->v_dns1));
|
||||
if (v->v_dns2.s_addr)
|
||||
printf(" DNS2:%s", ipaddr_string(&v->v_dns2));
|
||||
|
||||
/* IEN-116 name servers */
|
||||
if (v->v_ins1.s_addr)
|
||||
printf(" INS1:%s", ipaddr_string(&v->v_ins1));
|
||||
if (v->v_ins2.s_addr)
|
||||
printf(" INS2:%s", ipaddr_string(&v->v_ins2));
|
||||
|
||||
/* Time servers */
|
||||
if (v->v_ts1.s_addr)
|
||||
printf(" TS1:%s", ipaddr_string(&v->v_ts1));
|
||||
if (v->v_ts2.s_addr)
|
||||
printf(" TS2:%s", ipaddr_string(&v->v_ts2));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Print out arbitrary, unknown vendor data.
|
||||
*/
|
||||
|
||||
static void
|
||||
other_print(bp, length)
|
||||
register u_char *bp;
|
||||
int length;
|
||||
{
|
||||
u_char *ep; /* end pointer */
|
||||
u_char *zp; /* points one past last non-zero byte */
|
||||
register int i, j;
|
||||
|
||||
/* Setup end pointer */
|
||||
ep = bp + length;
|
||||
|
||||
/* Find the last non-zero byte. */
|
||||
for (zp = ep; zp > bp; zp--) {
|
||||
if (zp[-1] != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Print the all-zero case in a compact representation. */
|
||||
if (zp == bp) {
|
||||
printf("-all-zero");
|
||||
return;
|
||||
}
|
||||
printf("-unknown");
|
||||
|
||||
/* Are there enough trailing zeros to make "00..." worthwhile? */
|
||||
if (zp + 2 > ep)
|
||||
zp = ep; /* print them all normally */
|
||||
|
||||
/* Now just print all the non-zero data. */
|
||||
while (bp < zp) {
|
||||
printf(".%02X", *bp);
|
||||
bp++;
|
||||
}
|
||||
|
||||
if (zp < ep)
|
||||
printf(".00...");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
dump_hex(bp, len)
|
||||
u_char *bp;
|
||||
int len;
|
||||
{
|
||||
while (len > 0) {
|
||||
printf("%02X", *bp);
|
||||
bp++;
|
||||
len--;
|
||||
if (len) printf(".");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* tab-width: 4
|
||||
* c-indent-level: 4
|
||||
* c-argdecl-indent: 4
|
||||
* c-continued-statement-offset: 4
|
||||
* c-continued-brace-offset: -4
|
||||
* c-label-offset: -4
|
||||
* c-brace-offset: 0
|
||||
* End:
|
||||
*/
|
46
libexec/bootpd/trygetea.c
Normal file
46
libexec/bootpd/trygetea.c
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* trygetea.c - test program for getether.c
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#if defined(SUNOS) || defined(SVR4)
|
||||
#include <sys/sockio.h>
|
||||
#endif
|
||||
|
||||
#include <net/if.h> /* for struct ifreq */
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h> /* inet_ntoa */
|
||||
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
int debug = 0;
|
||||
char *progname;
|
||||
|
||||
main(argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
u_char ea[16]; /* Ethernet address */
|
||||
int i;
|
||||
|
||||
progname = argv[0]; /* for report */
|
||||
|
||||
if (argc < 2) {
|
||||
printf("need interface name\n");
|
||||
exit(1);
|
||||
}
|
||||
if ((i = getether(argv[1], ea)) < 0) {
|
||||
printf("Could not get Ethernet address (rc=%d)\n", i);
|
||||
exit(1);
|
||||
}
|
||||
printf("Ether-addr");
|
||||
for (i = 0; i < 6; i++)
|
||||
printf(":%x", ea[i] & 0xFF);
|
||||
printf("\n");
|
||||
|
||||
exit(0);
|
||||
}
|
68
libexec/bootpd/trygetif.c
Normal file
68
libexec/bootpd/trygetif.c
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* trygetif.c - test program for getif.c
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#if defined(SUNOS) || defined(SVR4)
|
||||
#include <sys/sockio.h>
|
||||
#endif
|
||||
|
||||
#include <net/if.h> /* for struct ifreq */
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h> /* inet_ntoa */
|
||||
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "getif.h"
|
||||
|
||||
int debug = 0;
|
||||
char *progname;
|
||||
|
||||
main(argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
struct hostent *hep;
|
||||
struct sockaddr ea; /* Ethernet address */
|
||||
struct sockaddr_in *sip; /* Interface address */
|
||||
struct ifreq *ifr;
|
||||
struct in_addr dst_addr;
|
||||
struct in_addr *dap;
|
||||
int i, s;
|
||||
|
||||
progname = argv[0]; /* for report */
|
||||
|
||||
dap = NULL;
|
||||
if (argc > 1) {
|
||||
dap = &dst_addr;
|
||||
if (isdigit(argv[1][0]))
|
||||
dst_addr.s_addr = inet_addr(argv[1]);
|
||||
else {
|
||||
hep = gethostbyname(argv[1]);
|
||||
if (!hep) {
|
||||
printf("gethostbyname(%s)\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
memcpy(&dst_addr, hep->h_addr, sizeof(dst_addr));
|
||||
}
|
||||
}
|
||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (s < 0) {
|
||||
perror("socket open");
|
||||
exit(1);
|
||||
}
|
||||
ifr = getif(s, dap);
|
||||
if (!ifr) {
|
||||
printf("no interface for address\n");
|
||||
exit(1);
|
||||
}
|
||||
printf("Intf-name:%s\n", ifr->ifr_name);
|
||||
sip = (struct sockaddr_in *) &(ifr->ifr_addr);
|
||||
printf("Intf-addr:%s\n", inet_ntoa(sip->sin_addr));
|
||||
|
||||
exit(0);
|
||||
}
|
50
libexec/bootpd/trylook.c
Normal file
50
libexec/bootpd/trylook.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* trylook.c - test program for lookup.c
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "report.h"
|
||||
#include "lookup.h"
|
||||
|
||||
extern char *ether_ntoa();
|
||||
extern char *inet_ntoa();
|
||||
|
||||
int debug = 0;
|
||||
char *progname;
|
||||
|
||||
main(argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
int i;
|
||||
struct in_addr in;
|
||||
char *a;
|
||||
u_char *hwa;
|
||||
|
||||
progname = argv[0]; /* for report */
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
|
||||
/* Host name */
|
||||
printf("%s:", argv[i]);
|
||||
|
||||
/* IP addr */
|
||||
if (lookup_ipa(argv[i], &in.s_addr))
|
||||
a = "?";
|
||||
else
|
||||
a = inet_ntoa(in);
|
||||
printf(" ipa=%s", a);
|
||||
|
||||
/* Ether addr */
|
||||
hwa = lookup_hwa(argv[i], 1);
|
||||
if (!hwa)
|
||||
a = "?";
|
||||
else
|
||||
a = ether_ntoa(hwa);
|
||||
printf(" hwa=%s\n", a);
|
||||
|
||||
}
|
||||
exit(0);
|
||||
}
|
44
libexec/bootpd/tzone.c
Normal file
44
libexec/bootpd/tzone.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* tzone.c - get the timezone
|
||||
*
|
||||
* This is shared by bootpd and bootpef
|
||||
*/
|
||||
|
||||
#ifdef SVR4
|
||||
/* XXX - Is this really SunOS specific? -gwr */
|
||||
/* This is in <time.h> but only visible if (__STDC__ == 1). */
|
||||
extern long timezone;
|
||||
#else /* SVR4 */
|
||||
/* BSD or SunOS */
|
||||
# include <sys/time.h>
|
||||
# include <syslog.h>
|
||||
#endif /* SVR4 */
|
||||
|
||||
#include "bptypes.h"
|
||||
#include "report.h"
|
||||
#include "tzone.h"
|
||||
|
||||
/* This is what other modules use. */
|
||||
int32 secondswest;
|
||||
|
||||
/*
|
||||
* Get our timezone offset so we can give it to clients if the
|
||||
* configuration file doesn't specify one.
|
||||
*/
|
||||
void
|
||||
tzone_init()
|
||||
{
|
||||
#ifdef SVR4
|
||||
/* XXX - Is this really SunOS specific? -gwr */
|
||||
secondswest = timezone;
|
||||
#else /* SVR4 */
|
||||
struct timezone tzp; /* Time zone offset for clients */
|
||||
struct timeval tp; /* Time (extra baggage) */
|
||||
if (gettimeofday(&tp, &tzp) < 0) {
|
||||
secondswest = 0; /* Assume GMT for lack of anything better */
|
||||
report(LOG_ERR, "gettimeofday: %s", get_errmsg());
|
||||
} else {
|
||||
secondswest = 60L * tzp.tz_minuteswest; /* Convert to seconds */
|
||||
}
|
||||
#endif /* SVR4 */
|
||||
}
|
3
libexec/bootpd/tzone.h
Normal file
3
libexec/bootpd/tzone.h
Normal file
@ -0,0 +1,3 @@
|
||||
/* tzone.h */
|
||||
extern int32 secondswest;
|
||||
extern void tzone_init();
|
Loading…
Reference in New Issue
Block a user