diff --git a/libexec/bootpd/.indent.pro b/libexec/bootpd/.indent.pro new file mode 100644 index 000000000000..177ed731e1b9 --- /dev/null +++ b/libexec/bootpd/.indent.pro @@ -0,0 +1,3 @@ + -nbad -nbap -nbbb -nbc -br -bli4 -c33 -cd33 -cdb -ce -ci4 + -cli0 -cp1 -d0 -di0 -nfc1 -nfca -i4 -ip4 -l75 -lp -npcs + -psl -sc -nsob -nss -ts4 diff --git a/libexec/bootpd/Announce b/libexec/bootpd/Announce index e4ae04c20d84..a76e18acd2a9 100644 --- a/libexec/bootpd/Announce +++ b/libexec/bootpd/Announce @@ -45,6 +45,7 @@ Problems fixed in this version: When lookup_hwa fails, assume numeric HW address. Systems on which I have seen this code work: + NetBSD-1.0 (BSD-4.4 derivative) SunOS 4.X (Solaris 1.X) SunOS 5.X (Solaris 2.X) System V/386 Rel. 4.0 @@ -52,7 +53,7 @@ Systems on which I have seen this code work: Systems on which others say this code works: CDC EP/IX (1.4.3, 2.1.1) DEC Ultrix (4.2, 4.3) - NetBSD (Current-8/94) + Linux 1.1.81 OSF/1 (DEC Alpha CPU) Please direct questions, comments, and bug reports to: diff --git a/libexec/bootpd/Changes b/libexec/bootpd/Changes index 06165486acc5..b08989e7b0aa 100644 --- a/libexec/bootpd/Changes +++ b/libexec/bootpd/Changes @@ -2,6 +2,53 @@ Changes, most recent first Date, Real Name what... +--> bootp-2.4.3 + +03/27/96 gwr@mc.com (Gordon W. Ross) + Use LOG_NOTICE in place of LOG_INFO for messages related + to unsatisfied clients [at request of ] + Fix the irix Makefile targets, and other misc. + +03/25/95 gwr@mc.com (Gordon W. Ross) + Corrected a bug I introduced into SunOS setarp, where + bad IP address caused "network unreachable" errors. + [Thanks to andrew@ntplx.net (Andrew Lindh) for the fix!] + +--> bootp-2.4.2 + +01/14/95 middelin@polyware.iaf.nl (Pauline Middelink) + Corrected support for the Linux networking code. + Fixed lots of warnings (gcc -Wall) + Added "linux" Makefile target. + +01/02/95 Jukka Ukkonen + Allow bootptab syntax: ha="0:0:c0:80:e8:a7" + +11/30/94 Tonny van Lankveld + Fix reporting of duplicate Ethernet addresses. + +09/06/94 longyear@netcom.com (Al Longyear) + Better setarp for linux, allows non-ether types. + +09/02/94 Robert MacKinnon + Add support for IBM's AIX 3.2.5 + +08/30/94 piercarl@ltd.c-d.com (Piercarlo Grandi) + Fix select calls on linux (modifies timeval arg). + Fix setarp (specify Ethernet type for now). + +08/27/94 drew@drewsun.FEITH.COM (Andrew B. Sudell) + Add support for Wollongong Win-TCP (SysVr4 variant). + +08/24/94 gwr@mc.com (Gordon W. Ross) + Use sigaction() on systems that define SA_NOCLDSTOP + (a symbol required by POSIX) for HP/UX and others. + +--> bootp-2.4.1 + +08/24/94 gwr@mc.com (Gordon W. Ross) + Fix bug in boot file name generation (missing init) + --> bootp-2.4.0 08/20/94 gwr@mc.com (Gordon W. Ross) diff --git a/libexec/bootpd/Makefile.UNIX b/libexec/bootpd/Makefile.UNIX index e333ce5d2ca8..701eb2bcc106 100644 --- a/libexec/bootpd/Makefile.UNIX +++ b/libexec/bootpd/Makefile.UNIX @@ -44,9 +44,7 @@ CFLAGS= $(OPTDEFS) $(SYSDEFS) $(FILEDEFS) $(MOREDEFS) PROGS= bootpd bootpef bootpgw bootptest TESTS= trylook trygetif trygetea -all: $(PROGS) - -tests: $(TESTS) +all: $(PROGS) $(TESTS) system: install @@ -76,7 +74,8 @@ distclean: -rm -f *.BAK *.CKP *~ .emacs* # -# Handy targets for individual systems: +# Handy targets for systems needing special treatment: +# (Most POSIX systems should work with just "make all") # # DEC/OSF1 on the Alpha @@ -96,9 +95,13 @@ epix211: SYSDEFS="-DSVR4" \ SYSLIBS="-lsocket -lnsl" -# Silicon Graphics IRIX (no , so not SVR4) +# IRIX 5.X (Silicon Graphics) irix: - $(MAKE) SYSDEFS="-DSYSV -DIRIX" + $(MAKE) SYSDEFS= SYSLIBS= + +# Linux 1.1.80+ on [34]86 +linux: + $(MAKE) SYSDEFS="-O6 -Wall -fomit-frame-pointer" # SunOS 4.X sunos4: @@ -110,11 +113,27 @@ sunos5: $(MAKE) SYSDEFS="-DSVR4 -DETC_ETHERS" \ SYSLIBS="-lsocket -lnsl" -# UNIX System V Rel. 4 (also: IRIX 5.X, others) +# Solaris 2.X (i.e. SunOS 5.X) with GCC. Note that GCC normally +# defines __STDC__=1 which breaks many Solaris header files... +sunos5gcc: + $(MAKE) SYSDEFS="-DSVR4 -DETC_ETHERS -D__STDC__=0" \ + SYSLIBS="-lsocket -lnsl" CC="gcc -Wall" + +# UNIX System V Rel. 3 +svr3: + $(MAKE) SYSDEFS="-DSYSV" + +# UNIX System V Rel. 4 svr4: $(MAKE) SYSDEFS="-DSVR4" \ SYSLIBS="-lsocket -lnsl" +# AT&T/GIS - Both AT&T StarServer and NCR 3000 +# may work for others using Wollongong's WIN-TCP +wollongong gis : + $(MAKE) SYSDEFS="-DSVR4 -DWIN_TCP" \ + SYSLIBS="-lsocket -lnsl" + # # How to build each program: # diff --git a/libexec/bootpd/Problems b/libexec/bootpd/Problems index 9478676eca40..78d809e6b215 100644 --- a/libexec/bootpd/Problems +++ b/libexec/bootpd/Problems @@ -1,6 +1,11 @@ Common problems and ways to work around them: +Bootpd complains: "bind: Address already in use" and fails to start. + You are already running something that has bound the + BOOTP listening port number. Check /etc/inetd.conf or + the equivalent for a bootp line (or in startup files). + Bootpd complains that it "can not get IP addr for HOSTNAME" If the entry is a "dummy" (not a real host) used only for @@ -45,3 +50,16 @@ not a fully specified path. :td=/tftpboot: (or) :hd=/usr/boot: (for example) +My PC clients running Sun's PC-NFS Pro v1.1 fail to receive +acceptable responses from the bootp server. + + These clients send a request with the DHCP "message length" + option and the (new) BOOTP "broadcast flag" both set. + The bootp server (on SunOS) will send a fragmented reply + unless you override the length with :ms=1024: (or less). + The "broadcast flag" is not yet supported, but there is + a simple work-around, just add :ra=255.255.255.255: + for any clients that need their reply broadcasted. + You may need to use a differnet broadcast address. + (Thanks to Ivan Auger ) + diff --git a/libexec/bootpd/README b/libexec/bootpd/README index c7755b786ddb..0901b2578598 100644 --- a/libexec/bootpd/README +++ b/libexec/bootpd/README @@ -90,6 +90,7 @@ Pittsburgh, PA 15213 Announce* Text of release announcements Changes Change history, reverse chronological +ConvOldTab.sh Script to convert old (1.x) bootptab files Installation Instructions for building and installing Makefile* for "make" README This file @@ -111,6 +112,7 @@ 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) +getether.h header for above getif.c Get network interface info. getif.h header for above hash.c The hash table module diff --git a/libexec/bootpd/ToDo b/libexec/bootpd/ToDo new file mode 100644 index 000000000000..261d24c72695 --- /dev/null +++ b/libexec/bootpd/ToDo @@ -0,0 +1,61 @@ +ToDo: -*- text -*- + +---------------------------------------------------------------------- +Memory allocation locality: + +Currently mallocs memory in a very haphazard manner. As such, most of +the program ends up core-resident all the time just to follow all the +stupid pointers around. . . . + +---------------------------------------------------------------------- +Input parser: + +The reader implemented in readfile.c could use improvement. Some sort +of "data-driven" parser should be used so the big switch statements +would have only one case for each data type instead of one case for +every recognized option symbol. Then adding a new tag would involve +only adding a new element to the data table describing known symbols. +Hopefully, this would shrink the code a bit too. -gwr + +---------------------------------------------------------------------- +SLIP Initialization via BOOTP: + +In the function handle_request(), both in bootpd and bootpgw, +we might want to add code like the following just before testing +the client IP address field for zero. (bp->bp_ciaddr == 0) +(David suggests we leave this out for now. -gwr) + +#if 1 /* XXX - Experimental */ + /* + * SLIP initialization support. + * + * If this packet came from a SLIP driver that does + * automatic IP address initialization, then the socket + * will have the IP address and the packet will + * have zeros for both the IP and HW addresses. + * + * Thanks to David P. Maynard + * for explaining how this works. -gwr + */ + if ((bp->bp_ciaddr.s_addr == 0) && + (bp->bp_htype == 0)) + { + /* Pretend the client knows its address. It will soon. */ + bp->bp_ciaddr = recv_addr.sin_addr; + if (debug) + report(LOG_INFO, "fixed blank request from IP addr %s", + inet_ntoa(recv_addr.sin_addr)); + } +#endif + +---------------------------------------------------------------------- +DHCP Support: + +There is a set of patches from Jeanette Pauline Middelink + to add DHCP support. + +Those patches will be integrated into the BOOTP release stream +very soon, but if you can't wait, you can get them from: +nimbus.anu.edu.au:/pub/tridge/samba/contributed/DHCP.patch + +---------------------------------------------------------------------- diff --git a/libexec/bootpd/bootp.h b/libexec/bootpd/bootp.h index 0651aa5dbfb0..23c0a2161b0b 100644 --- a/libexec/bootpd/bootp.h +++ b/libexec/bootpd/bootp.h @@ -23,7 +23,7 @@ SOFTWARE. /* * Bootstrap Protocol (BOOTP). RFC951 and RFC1395. * - * $Id: bootp.h,v 1.1.1.1 1994/09/10 14:44:54 csgr Exp $ + * $Id: bootp.h $ * * * This file specifies the "implementation-independent" BOOTP protocol diff --git a/libexec/bootpd/bootpd.c b/libexec/bootpd/bootpd.c index cf693fd6cc0c..745de7e22d8f 100644 --- a/libexec/bootpd/bootpd.c +++ b/libexec/bootpd/bootpd.c @@ -20,10 +20,6 @@ ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ************************************************************************/ -#ifndef lint -static char rcsid[] = "$Id: bootpd.c,v 1.1.1.1 1994/09/30 05:45:04 pst Exp $"; -#endif - /* * BOOTP (bootstrap protocol) server daemon. * @@ -49,6 +45,7 @@ static char rcsid[] = "$Id: bootpd.c,v 1.1.1.1 1994/09/30 05:45:04 pst Exp $"; #include #include #include +#include #include #include @@ -57,6 +54,7 @@ static char rcsid[] = "$Id: bootpd.c,v 1.1.1.1 1994/09/30 05:45:04 pst Exp $"; #ifndef NO_UNISTD #include #endif + #include #include #include @@ -71,11 +69,6 @@ static char rcsid[] = "$Id: bootpd.c,v 1.1.1.1 1994/09/30 05:45:04 pst Exp $"; # include /* for O_RDONLY, etc */ #endif -#ifdef SVR4 -/* Using sigset() avoids the need to re-arm each time. */ -#define signal sigset -#endif - #ifndef USE_BFUNCS # include /* Yes, memcpy is OK here (no overlapped copies). */ @@ -164,9 +157,11 @@ char *pktbuf; /* Receive packet buffer */ int pktlen; char *progname; char *chdir_path; -char hostname[MAXHOSTNAMELEN]; /* System host name */ struct in_addr my_ip_addr; +struct utsname my_uname; +char *hostname; + /* Flags set by signal catcher. */ PRIVATE int do_readtab = 0; PRIVATE int do_dumptab = 0; @@ -198,6 +193,9 @@ main(argc, argv) int n, ba_len, ra_len; int nfound, readfds; int standalone; +#ifdef SA_NOCLDSTOP /* Have POSIX sigaction(2). */ + struct sigaction sa; +#endif progname = strrchr(argv[0], '/'); if (progname) progname++; @@ -255,6 +253,12 @@ main(argc, argv) stmp = NULL; timeout = &actualtimeout; + if (uname(&my_uname) < 0) { + fprintf(stderr, "bootpd: can't get hostname\n"); + exit(1); + } + hostname = my_uname.nodename; + /* * Read switches. */ @@ -315,7 +319,7 @@ main(argc, argv) "bootpd: missing hostname\n"); break; } - strncpy(hostname, stmp, sizeof(hostname)-1); + hostname = stmp; break; case 'i': /* inetd mode */ @@ -369,12 +373,7 @@ main(argc, argv) /* * Get my hostname and IP address. */ - if (hostname[0] == '\0') { - if (gethostname(hostname, sizeof(hostname)) == -1) { - fprintf(stderr, "bootpd: can't get hostname\n"); - exit(1); - } - } + hep = gethostbyname(hostname); if (!hep) { fprintf(stderr, "Can not get my IP address\n"); @@ -481,6 +480,20 @@ main(argc, argv) /* * Set up signals to read or dump the table. */ +#ifdef SA_NOCLDSTOP /* Have POSIX sigaction(2). */ + sa.sa_handler = catcher; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + if (sigaction(SIGHUP, &sa, NULL) < 0) { + report(LOG_ERR, "sigaction: %s", get_errmsg()); + exit(1); + } + if (sigaction(SIGUSR1, &sa, NULL) < 0) { + report(LOG_ERR, "sigaction: %s", get_errmsg()); + exit(1); + } +#else /* SA_NOCLDSTOP */ + /* Old-fashioned UNIX signals */ if ((int) signal(SIGHUP, catcher) < 0) { report(LOG_ERR, "signal: %s", get_errmsg()); exit(1); @@ -489,13 +502,20 @@ main(argc, argv) report(LOG_ERR, "signal: %s", get_errmsg()); exit(1); } +#endif /* SA_NOCLDSTOP */ /* * Process incoming requests. */ for (;;) { + struct timeval tv; + readfds = 1 << s; - nfound = select(s + 1, (fd_set *)&readfds, NULL, NULL, timeout); + if (timeout) + tv = *timeout; + + nfound = select(s + 1, (fd_set *)&readfds, NULL, NULL, + (timeout) ? &tv : NULL); if (nfound < 0) { if (errno != EINTR) { report(LOG_ERR, "select: %s", get_errmsg()); @@ -532,7 +552,7 @@ main(argc, argv) } if (n < sizeof(struct bootp)) { if (debug) { - report(LOG_INFO, "received short packet"); + report(LOG_NOTICE, "received short packet"); } continue; } @@ -580,9 +600,8 @@ catcher(sig) do_readtab = 1; if (sig == SIGUSR1) do_dumptab = 1; -#ifdef SYSV - /* For older "System V" derivatives with no sigset(). */ - /* XXX - Should just do it the POSIX way (sigaction). */ +#if !defined(SA_NOCLDSTOP) && defined(SYSV) + /* For older "System V" derivatives with no sigaction(). */ signal(sig, catcher); #endif } @@ -676,8 +695,8 @@ HW addr type is IEEE 802. convert to %s and check again\n", /* * XXX - Add dynamic IP address assignment? */ - if (debug > 1) - report(LOG_INFO, "unknown client %s address %s", + if (debug) + report(LOG_NOTICE, "unknown client %s address %s", netname(bp->bp_htype), haddrtoa(bp->bp_chaddr, bp->bp_hlen)); return; /* not found */ @@ -698,7 +717,7 @@ HW addr type is IEEE 802. convert to %s and check again\n", hp = (struct host *) hash_Lookup(iphashtable, hashcode, iplookcmp, &dummyhost); if (hp == NULL) { - if (debug > 1) { + if (debug) { report(LOG_NOTICE, "IP address not found: %s", inet_ntoa(bp->bp_ciaddr)); } @@ -911,7 +930,9 @@ HW addr type is IEEE 802. convert to %s and check again\n", if (debug > 2) report(LOG_INFO, "bootfile=\"%s\"", clntpath); +#ifdef CHECK_FILE_ACCESS null_file_name: +#endif /* CHECK_FILE_ACCESS */ /* @@ -994,7 +1015,7 @@ sendreply(forward, dst_override) struct in_addr dst; u_short port = bootpc_port; unsigned char *ha; - int len; + int len, haf; /* * XXX - Should honor bp_flags "broadcast" bit here. @@ -1033,11 +1054,14 @@ sendreply(forward, dst_override) len = bp->bp_hlen; if (len > MAXHADDRLEN) len = MAXHADDRLEN; + haf = (int) bp->bp_htype; + if (haf == 0) + haf = HTYPE_ETHERNET; if (debug > 1) report(LOG_INFO, "setarp %s - %s", inet_ntoa(dst), haddrtoa(ha, len)); - setarp(s, &dst, ha, len); + setarp(s, &dst, haf, ha, len); } if ((forward == 0) && @@ -1206,7 +1230,6 @@ dovend_rfc1048(bp, hp, bootsize) { int bytesleft, len; byte *vp; - char *tmpstr; static char noroom[] = "%s: No room for \"%s\" option"; @@ -1235,7 +1258,7 @@ dovend_rfc1048(bp, hp, bootsize) byte *p, *ep; byte tag, len; short msgsz = 0; - + p = vp + 4; ep = p + BP_VEND_LEN - 4; while (p < ep) { diff --git a/libexec/bootpd/bootpgw/bootpgw.c b/libexec/bootpd/bootpgw/bootpgw.c new file mode 100644 index 000000000000..353d9173fead --- /dev/null +++ b/libexec/bootpd/bootpgw/bootpgw.c @@ -0,0 +1,687 @@ +/* + * bootpgw.c - BOOTP GateWay + * This program forwards BOOTP Request packets to a BOOTP server. + */ + +/************************************************************************ + 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. +************************************************************************/ + +/* + * BOOTPGW is typically used to forward BOOTP client requests from + * one subnet to a BOOTP server on a different subnet. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include /* inet_ntoa */ + +#ifndef NO_UNISTD +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef NO_SETSID +# include /* for O_RDONLY, etc */ +#endif + +#ifndef USE_BFUNCS +# include +/* 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 "getif.h" +#include "hwaddr.h" +#include "report.h" +#include "patchlevel.h" + +/* Local definitions: */ +#define MAX_MSG_SIZE (3*512) /* Maximum packet size */ +#define TRUE 1 +#define FALSE 0 +#define get_network_errmsg get_errmsg + + + +/* + * Externals, forward declarations, and global variables + */ + +#ifdef __STDC__ +#define P(args) args +#else +#define P(args) () +#endif + +static void usage P((void)); +static void handle_reply P((void)); +static void handle_request P((void)); + +#undef P + +/* + * 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 bind_addr; /* Listening */ +struct sockaddr_in recv_addr; /* Packet source */ +struct sockaddr_in send_addr; /* destination */ + + +/* + * option defaults + */ +int debug = 0; /* Debugging flag (level) */ +struct timeval actualtimeout = +{ /* fifteen minutes */ + 15 * 60L, /* tv_sec */ + 0 /* tv_usec */ +}; +u_int maxhops = 4; /* Number of hops allowed for requests. */ +u_int minwait = 3; /* Number of seconds client must wait before + its bootrequest packets are forwarded. */ + +/* + * General + */ + +int s; /* Socket file descriptor */ +char *pktbuf; /* Receive packet buffer */ +int pktlen; +char *progname; +char *servername; +int32 server_ipa; /* Real server IP address, network order. */ + +struct in_addr my_ip_addr; + +struct utsname my_uname; +char *hostname; + + + + + +/* + * 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 timeval *timeout; + struct bootp *bp; + struct servent *servp; + struct hostent *hep; + char *stmp; + int n, ba_len, ra_len; + int nfound, readfds; + int standalone; + + progname = strrchr(argv[0], '/'); + if (progname) progname++; + else progname = argv[0]; + + /* + * Initialize logging. + */ + report_init(0); /* uses progname */ + + /* + * Log startup + */ + report(LOG_INFO, "version %s.%d", VERSION, PATCHLEVEL); + + /* Debugging for compilers with struct padding. */ + assert(sizeof(struct bootp) == BP_MINPKTSZ); + + /* Get space for receiving packets and composing replies. */ + pktbuf = malloc(MAX_MSG_SIZE); + if (!pktbuf) { + report(LOG_ERR, "malloc failed"); + exit(1); + } + bp = (struct bootp *) pktbuf; + + /* + * Check to see if a socket was passed to us from inetd. + * + * Use getsockname() to determine if descriptor 0 is indeed a socket + * (and thus we are probably a child of inetd) or if it is instead + * something else and we are running standalone. + */ + s = 0; + ba_len = sizeof(bind_addr); + bzero((char *) &bind_addr, ba_len); + errno = 0; + standalone = TRUE; + if (getsockname(s, (struct sockaddr *) &bind_addr, &ba_len) == 0) { + /* + * Descriptor 0 is a socket. Assume we are a child of inetd. + */ + if (bind_addr.sin_family == AF_INET) { + standalone = FALSE; + bootps_port = ntohs(bind_addr.sin_port); + } else { + /* Some other type of socket? */ + report(LOG_INFO, "getsockname: not an INET socket"); + } + } + /* + * Set defaults that might be changed by option switches. + */ + stmp = NULL; + timeout = &actualtimeout; + + if (uname(&my_uname) < 0) { + fprintf(stderr, "bootpgw: can't get hostname\n"); + exit(1); + } + hostname = my_uname.nodename; + + hep = gethostbyname(hostname); + if (!hep) { + printf("Can not get my IP address\n"); + exit(1); + } + bcopy(hep->h_addr, (char *)&my_ip_addr, sizeof(my_ip_addr)); + + /* + * Read switches. + */ + for (argc--, argv++; argc > 0; argc--, argv++) { + if (argv[0][0] != '-') + break; + switch (argv[0][1]) { + + case 'd': /* debug level */ + 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, + "%s: invalid debug level\n", progname); + break; + } + debug = n; + break; + + case 'h': /* hop count limit */ + if (argv[0][2]) { + stmp = &(argv[0][2]); + } else { + argc--; + argv++; + stmp = argv[0]; + } + if (!stmp || (sscanf(stmp, "%d", &n) != 1) || + (n < 0) || (n > 16)) + { + fprintf(stderr, + "bootpgw: invalid hop count limit\n"); + break; + } + maxhops = (u_int)n; + break; + + case 'i': /* inetd mode */ + standalone = FALSE; + break; + + case 's': /* standalone mode */ + standalone = TRUE; + break; + + case 't': /* timeout */ + if (argv[0][2]) { + stmp = &(argv[0][2]); + } else { + argc--; + argv++; + stmp = argv[0]; + } + if (!stmp || (sscanf(stmp, "%d", &n) != 1) || (n < 0)) { + fprintf(stderr, + "%s: invalid timeout specification\n", progname); + break; + } + actualtimeout.tv_sec = (int32) (60 * n); + /* + * If the actual timeout is zero, pass a NULL pointer + * to select so it blocks indefinitely, otherwise, + * point to the actual timeout value. + */ + timeout = (n > 0) ? &actualtimeout : NULL; + break; + + case 'w': /* wait time */ + if (argv[0][2]) { + stmp = &(argv[0][2]); + } else { + argc--; + argv++; + stmp = argv[0]; + } + if (!stmp || (sscanf(stmp, "%d", &n) != 1) || + (n < 0) || (n > 60)) + { + fprintf(stderr, + "bootpgw: invalid wait time\n"); + break; + } + minwait = (u_int)n; + break; + + default: + fprintf(stderr, "%s: unknown switch: -%c\n", + progname, argv[0][1]); + usage(); + break; + + } /* switch */ + } /* for args */ + + /* Make sure server name argument is suplied. */ + servername = argv[0]; + if (!servername) { + fprintf(stderr, "bootpgw: missing server name\n"); + usage(); + } + /* + * Get address of real bootp server. + */ + if (isdigit(servername[0])) + server_ipa = inet_addr(servername); + else { + hep = gethostbyname(servername); + if (!hep) { + fprintf(stderr, "bootpgw: can't get addr for %s\n", servername); + exit(1); + } + bcopy(hep->h_addr, (char *)&server_ipa, sizeof(server_ipa)); + } + + if (standalone) { + /* + * Go into background and disassociate from controlling terminal. + * XXX - This is not the POSIX way (Should use setsid). -gwr + */ + if (debug < 3) { + if (fork()) + exit(0); +#ifdef NO_SETSID + setpgrp(0,0); +#ifdef TIOCNOTTY + n = open("/dev/tty", O_RDWR); + if (n >= 0) { + ioctl(n, TIOCNOTTY, (char *) 0); + (void) close(n); + } +#endif /* TIOCNOTTY */ +#else /* SETSID */ + if (setsid() < 0) + perror("setsid"); +#endif /* SETSID */ + } /* if debug < 3 */ + /* + * Nuke any timeout value + */ + timeout = NULL; + + /* + * Here, bootpd would do: + * chdir + * tzone_init + * rdtab_init + * readtab + */ + + /* + * Create a socket. + */ + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + report(LOG_ERR, "socket: %s", get_network_errmsg()); + exit(1); + } + /* + * Get server's listening port number + */ + servp = getservbyname("bootps", "udp"); + if (servp) { + bootps_port = ntohs((u_short) servp->s_port); + } else { + bootps_port = (u_short) IPPORT_BOOTPS; + report(LOG_ERR, + "udp/bootps: unknown service -- assuming port %d", + bootps_port); + } + + /* + * Bind socket to BOOTPS port. + */ + bind_addr.sin_family = AF_INET; + bind_addr.sin_port = htons(bootps_port); + bind_addr.sin_addr.s_addr = INADDR_ANY; + if (bind(s, (struct sockaddr *) &bind_addr, + sizeof(bind_addr)) < 0) + { + report(LOG_ERR, "bind: %s", get_network_errmsg()); + exit(1); + } + } /* if standalone */ + /* + * Get destination port number so we can reply to client + */ + servp = getservbyname("bootpc", "udp"); + if (servp) { + bootpc_port = ntohs(servp->s_port); + } else { + report(LOG_ERR, + "udp/bootpc: unknown service -- assuming port %d", + IPPORT_BOOTPC); + bootpc_port = (u_short) IPPORT_BOOTPC; + } + + /* no signal catchers */ + + /* + * Process incoming requests. + */ + for (;;) { + struct timeval tv; + + readfds = 1 << s; + if (timeout) + tv = *timeout; + + nfound = select(s + 1, (fd_set *)&readfds, NULL, NULL, + (timeout) ? &tv : NULL); + if (nfound < 0) { + if (errno != EINTR) { + report(LOG_ERR, "select: %s", get_errmsg()); + } + continue; + } + if (!(readfds & (1 << s))) { + report(LOG_INFO, "exiting after %ld minutes of inactivity", + actualtimeout.tv_sec / 60); + exit(0); + } + ra_len = sizeof(recv_addr); + n = recvfrom(s, pktbuf, MAX_MSG_SIZE, 0, + (struct sockaddr *) &recv_addr, &ra_len); + if (n <= 0) { + continue; + } + if (debug > 3) { + report(LOG_INFO, "recvd pkt from IP addr %s", + inet_ntoa(recv_addr.sin_addr)); + } + if (n < sizeof(struct bootp)) { + if (debug) { + report(LOG_INFO, "received short packet"); + } + continue; + } + pktlen = n; + + switch (bp->bp_op) { + case BOOTREQUEST: + handle_request(); + break; + case BOOTREPLY: + handle_reply(); + break; + } + } +} + + + + +/* + * Print "usage" message and exit + */ + +static void +usage() +{ + fprintf(stderr, + "usage: bootpgw [-d level] [-i] [-s] [-t timeout] server\n"); + fprintf(stderr, "\t -d n\tset debug level\n"); + fprintf(stderr, "\t -h n\tset max hop count\n"); + fprintf(stderr, "\t -i\tforce inetd mode (run as child of inetd)\n"); + fprintf(stderr, "\t -s\tforce standalone mode (run without inetd)\n"); + fprintf(stderr, "\t -t n\tset inetd exit timeout to n minutes\n"); + fprintf(stderr, "\t -w n\tset min wait time (secs)\n"); + exit(1); +} + + + +/* + * Process BOOTREQUEST packet. + * + * Note, this just forwards the request to a real server. + */ +static void +handle_request() +{ + struct bootp *bp = (struct bootp *) pktbuf; + u_short secs, hops; + + /* XXX - SLIP init: Set bp_ciaddr = recv_addr here? */ + + if (debug) { + report(LOG_INFO, "request from %s", + inet_ntoa(recv_addr.sin_addr)); + } + /* Has the client been waiting long enough? */ + secs = ntohs(bp->bp_secs); + if (secs < minwait) + return; + + /* Has this packet hopped too many times? */ + hops = ntohs(bp->bp_hops); + if (++hops > maxhops) { + report(LOG_NOTICE, "reqest from %s reached hop limit", + inet_ntoa(recv_addr.sin_addr)); + return; + } + bp->bp_hops = htons(hops); + + /* + * Here one might discard a request from the same subnet as the + * real server, but we can assume that the real server will send + * a reply to the client before it waits for minwait seconds. + */ + + /* If gateway address is not set, put in local interface addr. */ + if (bp->bp_giaddr.s_addr == 0) { +#if 0 /* BUG */ + struct sockaddr_in *sip; + struct ifreq *ifr; + /* + * XXX - This picks the wrong interface when the receive addr + * is the broadcast address. There is no portable way to + * find out which interface a broadcast was received on. -gwr + * (Thanks to for finding this bug!) + */ + ifr = getif(s, &recv_addr.sin_addr); + if (!ifr) { + report(LOG_NOTICE, "no interface for request from %s", + inet_ntoa(recv_addr.sin_addr)); + return; + } + sip = (struct sockaddr_in *) &(ifr->ifr_addr); + bp->bp_giaddr = sip->sin_addr; +#else /* BUG */ + /* + * XXX - Just set "giaddr" to our "official" IP address. + * RFC 1532 says giaddr MUST be set to the address of the + * interface on which the request was received. Setting + * it to our "default" IP address is not strictly correct, + * but is good enough to allow the real BOOTP server to + * get the reply back here. Then, before we forward the + * reply to the client, the giaddr field is corrected. + * (In case the client uses giaddr, which it should not.) + * See handle_reply() + */ + bp->bp_giaddr = my_ip_addr; +#endif /* BUG */ + + /* + * XXX - DHCP says to insert a subnet mask option into the + * options area of the request (if vendor magic == std). + */ + } + /* Set up socket address for send. */ + send_addr.sin_family = AF_INET; + send_addr.sin_port = htons(bootps_port); + send_addr.sin_addr.s_addr = server_ipa; + + /* Send reply with same size packet as request used. */ + if (sendto(s, pktbuf, pktlen, 0, + (struct sockaddr *) &send_addr, + sizeof(send_addr)) < 0) + { + report(LOG_ERR, "sendto: %s", get_network_errmsg()); + } +} + + + +/* + * Process BOOTREPLY packet. + */ +static void +handle_reply() +{ + struct bootp *bp = (struct bootp *) pktbuf; + struct ifreq *ifr; + struct sockaddr_in *sip; + unsigned char *ha; + int len, haf; + + if (debug) { + report(LOG_INFO, " reply for %s", + inet_ntoa(bp->bp_yiaddr)); + } + /* Make sure client is directly accessible. */ + ifr = getif(s, &(bp->bp_yiaddr)); + if (!ifr) { + report(LOG_NOTICE, "no interface for reply to %s", + inet_ntoa(bp->bp_yiaddr)); + return; + } +#if 1 /* Experimental (see BUG above) */ +/* #ifdef CATER_TO_OLD_CLIENTS ? */ + /* + * The giaddr field has been set to our "default" IP address + * which might not be on the same interface as the client. + * In case the client looks at giaddr, (which it should not) + * giaddr is now set to the address of the correct interface. + */ + sip = (struct sockaddr_in *) &(ifr->ifr_addr); + bp->bp_giaddr = sip->sin_addr; +#endif + + /* Set up socket address for send to client. */ + send_addr.sin_family = AF_INET; + send_addr.sin_addr = bp->bp_yiaddr; + send_addr.sin_port = htons(bootpc_port); + + /* Create an ARP cache entry for the client. */ + ha = bp->bp_chaddr; + len = bp->bp_hlen; + if (len > MAXHADDRLEN) + len = MAXHADDRLEN; + haf = (int) bp->bp_htype; + if (haf == 0) + haf = HTYPE_ETHERNET; + + if (debug > 1) + report(LOG_INFO, "setarp %s - %s", + inet_ntoa(bp->bp_yiaddr), haddrtoa(ha, len)); + setarp(s, &bp->bp_yiaddr, haf, ha, len); + + /* Send reply with same size packet as request used. */ + if (sendto(s, pktbuf, pktlen, 0, + (struct sockaddr *) &send_addr, + sizeof(send_addr)) < 0) + { + report(LOG_ERR, "sendto: %s", get_network_errmsg()); + } +} + +/* + * 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: + */ diff --git a/libexec/bootpd/bootptab.5 b/libexec/bootpd/bootptab.5 index 74953837f6e9..c79116a617b9 100644 --- a/libexec/bootpd/bootptab.5 +++ b/libexec/bootpd/bootptab.5 @@ -1,6 +1,6 @@ .\" 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 $ +.\" $Header: $ .\" .TH BOOTPTAB 5 "October 31, 1991" "Carnegie Mellon University" .UC 6 diff --git a/libexec/bootpd/bootptab.mcs b/libexec/bootpd/bootptab.mcs index 6fa04d1347eb..2f8b3a6ff304 100644 --- a/libexec/bootpd/bootptab.mcs +++ b/libexec/bootpd/bootptab.mcs @@ -85,8 +85,5 @@ tp885: tc=.subnet17:ha=08.00.4C.00.2F.74:bf=tp885sys2.cfe: #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: +bach: tc=.subnet16:ha="08:00:20:04:98:8d":bf=boot.sun4m: +xanadu:tc=.subnet17:ha="00:80:42:42:04:c7":bf=boot.sun4c: diff --git a/libexec/bootpd/dovend.c b/libexec/bootpd/dovend.c index ba6ab288b8b3..e46ae9e4308d 100644 --- a/libexec/bootpd/dovend.c +++ b/libexec/bootpd/dovend.c @@ -56,7 +56,6 @@ dovend_rfc1497(hp, buf, len) { int bytesleft = len; byte *vp = buf; - char *tmpstr; static char noroom[] = "%s: No room for \"%s\" option"; #define NEED(LEN, MSG) do \ @@ -220,7 +219,7 @@ dovend_rfc1497(hp, buf, len) * Not enough room for full (domain-qualified) hostname, try * stripping it down to just the first field (host). */ - tmpstr = hp->hostname->string; + char *tmpstr = hp->hostname->string; len = 0; while (*tmpstr && (*tmpstr != '.')) { tmpstr++; diff --git a/libexec/bootpd/dumptab.c b/libexec/bootpd/dumptab.c index 5893f6c4a23e..8c049b99deba 100644 --- a/libexec/bootpd/dumptab.c +++ b/libexec/bootpd/dumptab.c @@ -59,7 +59,7 @@ dumptab(filename) int n; struct host *hp; FILE *fp; - time_t t; + 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\ diff --git a/libexec/bootpd/getether.c b/libexec/bootpd/getether.c index 724a3767d3a7..a96a4bb1b2ae 100644 --- a/libexec/bootpd/getether.c +++ b/libexec/bootpd/getether.c @@ -11,9 +11,14 @@ #include #include +#ifndef NO_UNISTD +#include +#endif + #include #include +#include "getether.h" #include "report.h" #define EALEN 6 @@ -101,7 +106,7 @@ getether(ifname, eap) #endif /* SUNOS */ -#if defined(__FreeBSD__) || defined(__NetBSD__) +#if defined(__386BSD__) || defined(__NetBSD__) /* Thanks to John Brezak for this code. */ #include #include @@ -168,10 +173,12 @@ getether(ifname, eap) #include #include #include +#include #ifndef NULL #define NULL 0 #endif +int getether(ifname, eap) char *ifname; /* interface name from ifconfig structure */ char *eap; /* Ether address (output) */ @@ -308,30 +315,31 @@ getether(ifname, eap) #endif /* SVR4 */ -#ifdef linux +#ifdef __linux__ /* * This is really easy on Linux! This version (for linux) - * written by Nigel Metheringham + * written by Nigel Metheringham and + * updated by Pauline Middelink * * 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 #include #include /* struct ifreq */ +#include /* Needed for IOCTL defs */ -/* 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 /* Needed for IOCTL defs */ - +int getether(ifname, eap) char *ifname, *eap; { int rc = -1; int fd; struct ifreq phys; - bzero(&phys, sizeof(phys)); + + memset(&phys, 0, sizeof(phys)); strcpy(phys.ifr_name, ifname); if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { report(LOG_ERR, "getether: socket(INET,DGRAM) failed"); @@ -340,7 +348,7 @@ getether(ifname, eap) if (ioctl(fd, SIOCGIFHWADDR, &phys) < 0) { report(LOG_ERR, "getether: ioctl SIOCGIFHWADDR failed"); } else { - bcopy(phys.ifr_hwaddr, eap, EALEN); + memcpy(eap, &phys.ifr_hwaddr.sa_data, EALEN); rc = 0; } close(fd); @@ -348,11 +356,12 @@ getether(ifname, eap) } #define GETETHER -#endif /* linux */ +#endif /* __linux__ */ /* If we don't know how on this system, just return an error. */ #ifndef GETETHER +int getether(ifname, eap) char *ifname, *eap; { diff --git a/libexec/bootpd/getether.h b/libexec/bootpd/getether.h new file mode 100644 index 000000000000..2f98299278c6 --- /dev/null +++ b/libexec/bootpd/getether.h @@ -0,0 +1,7 @@ +/* getether.h */ + +#ifdef __STDC__ +extern int getether(char *ifname, char *eaptr); +#else +extern int getether(); +#endif diff --git a/libexec/bootpd/getif.c b/libexec/bootpd/getif.c index 6cc16496ae46..de9f96d29577 100644 --- a/libexec/bootpd/getif.c +++ b/libexec/bootpd/getif.c @@ -13,6 +13,9 @@ #include #endif +#ifdef _AIX32 +#include /* for struct timeval in net/if.h */ +#endif #include /* for struct ifreq */ #include diff --git a/libexec/bootpd/hash.c b/libexec/bootpd/hash.c index 2ecda6305a25..9637c9ae85dc 100644 --- a/libexec/bootpd/hash.c +++ b/libexec/bootpd/hash.c @@ -20,11 +20,6 @@ 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 * diff --git a/libexec/bootpd/hwaddr.c b/libexec/bootpd/hwaddr.c index 840b95333567..191fadced5de 100644 --- a/libexec/bootpd/hwaddr.c +++ b/libexec/bootpd/hwaddr.c @@ -17,8 +17,19 @@ #include #endif +#ifdef _AIX32 +#include /* for struct timeval in net/if.h */ +#include /* for struct ifnet in net/if_arp.h */ +#endif + #include #include + +#ifdef WIN_TCP +#include +#include +#endif + #include #ifndef NO_UNISTD #include @@ -33,11 +44,8 @@ #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 +#ifndef ATF_INUSE /* Not defined on some systems (i.e. Linux) */ +#define ATF_INUSE 0 #endif #include "bptypes.h" @@ -72,21 +80,43 @@ int hwinfocnt = sizeof(hwinfolist) / sizeof(hwinfolist[0]); * bound to hardware address 'ha' of length 'len'. */ void -setarp(s, ia, ha, len) +setarp(s, ia, hafamily, haddr, halen) int s; /* socket fd */ - struct in_addr *ia; - u_char *ha; - int len; + struct in_addr *ia; /* protocol address */ + int hafamily; /* HW address family */ + u_char *haddr; /* HW address data */ + int halen; { #ifdef SIOCSARP +#ifdef WIN_TCP + /* This is an SVR4 with different networking code from + * Wollongong WIN-TCP. Not quite like the Lachman code. + * Code from: drew@drewsun.FEITH.COM (Andrew B. Sudell) + */ +#undef SIOCSARP +#define SIOCSARP ARP_ADD + struct arptab arpreq; /* Arp table entry */ + + bzero((caddr_t) &arpreq, sizeof(arpreq)); + arpreq.at_flags = ATF_COM; + + /* Set up IP address */ + arpreq.at_in = ia->s_addr; + + /* Set up Hardware Address */ + bcopy(haddr, arpreq.at_enaddr, halen); + + /* Set the Date Link type. */ + /* XXX - Translate (hafamily) to dltype somehow? */ + arpreq.at_dltype = DL_ETHER; + +#else /* WIN_TCP */ + /* Good old Berkeley way. */ struct arpreq arpreq; /* Arp request ioctl block */ struct sockaddr_in *si; -#ifdef SVR4 - int fd; - struct strioctl iocb; -#endif /* SVR4 */ + char *p; - bzero((caddr_t) & arpreq, sizeof(arpreq)); + bzero((caddr_t) &arpreq, sizeof(arpreq)); arpreq.arp_flags = ATF_INUSE | ATF_COM; /* Set up the protocol address. */ @@ -95,7 +125,18 @@ setarp(s, ia, ha, len) si->sin_addr = *ia; /* Set up the hardware address. */ - bcopy(ha, arpreq.arp_ha.sa_data, len); +#ifdef __linux__ /* XXX - Do others need this? -gwr */ + /* + * Linux requires the sa_family field set. + * longyear@netcom.com (Al Longyear) + */ + arpreq.arp_ha.sa_family = hafamily; +#endif /* linux */ + + /* This variable is just to help catch type mismatches. */ + p = arpreq.arp_ha.sa_data; + bcopy(haddr, p, halen); +#endif /* WIN_TCP */ #ifdef SVR4 /* @@ -106,18 +147,22 @@ setarp(s, ia, ha, len) * bear@upsys.se (Bj|rn Sj|holm), * Michael Kuschke , */ - 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); + { + int fd; + struct strioctl iocb; + 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 @@ -125,30 +170,30 @@ setarp(s, ia, ha, len) * to add is already in the cache. (Sigh...) * XXX - Should this error simply be ignored? -gwr */ - if (ioctl(s, SIOCSARP, (caddr_t) & arpreq) < 0) { + 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). + * Need to delete partial entry first on some systems. * XXX - Gag! */ - char buf[256]; int status; + char buf[256]; + char *a; + extern char *inet_ntoa(); - sprintf(buf, "arp -s %s %s temp", - inet_ntoa(*ia), haddrtoa(ha, len)); + a = inet_ntoa(*ia); + sprintf(buf, "arp -d %s; arp -s %s %s temp", + a, a, haddrtoa(haddr, halen)); 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 */ } diff --git a/libexec/bootpd/hwaddr.h b/libexec/bootpd/hwaddr.h index dea7158be8c7..8b40799feff1 100644 --- a/libexec/bootpd/hwaddr.h +++ b/libexec/bootpd/hwaddr.h @@ -23,7 +23,7 @@ extern int hwinfocnt; #define P(args) () #endif -extern void setarp P((int, struct in_addr *, u_char *, int)); +extern void setarp P((int, struct in_addr *, int, u_char *, int)); extern char *haddrtoa P((u_char *, int)); extern void haddr_conv802 P((u_char *, u_char *, int)); diff --git a/libexec/bootpd/lookup.c b/libexec/bootpd/lookup.c index 2a30a59b2c39..c99f1b80da0e 100644 --- a/libexec/bootpd/lookup.c +++ b/libexec/bootpd/lookup.c @@ -5,6 +5,9 @@ #include #include +#ifdef _AIX32 +#include /* for struct timeval in net/if.h */ +#endif #include #include diff --git a/libexec/bootpd/patchlevel.h b/libexec/bootpd/patchlevel.h index 782959e3c750..3909c641874e 100644 --- a/libexec/bootpd/patchlevel.h +++ b/libexec/bootpd/patchlevel.h @@ -1,3 +1,3 @@ /* patchlevel.h */ #define VERSION "2.4" -#define PATCHLEVEL 1 +#define PATCHLEVEL 3 diff --git a/libexec/bootpd/readfile.c b/libexec/bootpd/readfile.c index 4a9d9937dd5c..f7fbdc07f520 100644 --- a/libexec/bootpd/readfile.c +++ b/libexec/bootpd/readfile.c @@ -20,11 +20,6 @@ ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ************************************************************************/ -#ifndef lint -static char rcsid[] = "$Id: readfile.c,v 1.1.1.1 1994/09/10 14:44:55 csgr Exp $"; -#endif - - /* * bootpd configuration file reading code. * @@ -446,7 +441,7 @@ readtab(force) if (hash_Insert(hwhashtable, hashcode, hwinscmp, hp, hp) < 0) { report(LOG_NOTICE, "duplicate %s address: %s", netname(hp->htype), - haddrtoa(hp->haddr, hp->htype)); + haddrtoa(hp->haddr, haddrlength(hp->htype))); free_host((hash_datum *) hp); continue; } @@ -768,8 +763,8 @@ process_entry(host, src) } \ } while (0) -/* Parse an integer value for MEMBER */ -#define PARSE_INT(MEMBER) do \ +/* Parse an unsigned integer value for MEMBER */ +#define PARSE_UINT(MEMBER) do \ { \ if (optype == OP_BOOLEAN) \ return E_SYNTAX_ERROR; \ @@ -796,7 +791,6 @@ eval_symbol(symbol, hp) { char tmpstr[MAXSTRINGLEN]; byte *tmphaddr; - struct shared_string *ss; struct symbolmap *symbolptr; u_int32 value; int32 timeoff; @@ -820,7 +814,7 @@ eval_symbol(symbol, hp) if ((*symbol)[0] == 'T') { /* generic symbol */ (*symbol)++; value = get_u_long(symbol); - sprintf(current_tagname, "T%d", value); + sprintf(current_tagname, "T%d", (int)value); eat_whitespace(symbol); if ((*symbol)[0] != '=') { return E_SYNTAX_ERROR; @@ -985,7 +979,7 @@ eval_symbol(symbol, hp) if (!strncmp(tmpstr, "auto", 4)) { hp->time_offset = secondswest; } else { - if (sscanf(tmpstr, "%d", &timeoff) != 1) + if (sscanf(tmpstr, "%d", (int*)&timeoff) != 1) return E_BAD_LONGWORD; hp->time_offset = timeoff; } @@ -1121,16 +1115,14 @@ eval_symbol(symbol, hp) #endif case SYM_MSG_SIZE: - PARSE_INT(msg_size); + PARSE_UINT(msg_size); if (hp->msg_size < BP_MINPKTSZ || hp->msg_size > MAX_MSG_SIZE) return E_BAD_VALUE; break; case SYM_MIN_WAIT: - PARSE_INT(min_wait); - if (hp->min_wait < 0) - return E_BAD_VALUE; + PARSE_UINT(min_wait); break; /* XXX - Add new tags here */ @@ -1682,7 +1674,6 @@ prs_inetaddr(src, result) int n; char *s, *t; -#if 1 /* XXX - experimental */ /* Leading alpha char causes IP addr lookup. */ if (isalpha(**src)) { /* Lookup IP address. */ @@ -1700,7 +1691,6 @@ prs_inetaddr(src, result) report(LOG_ERR, "can not get IP addr for %s", tmpstr); return n; } -#endif /* * Parse an address in Internet format: @@ -1794,7 +1784,6 @@ prs_haddr(src, htype) get_string(src, tmpstr, &tmplen); p = tmpstr; -#if 1 /* XXX - experimental */ /* If it's a valid host name, try to lookup the HW address. */ if (goodname(p)) { /* Lookup Hardware Address for hostname. */ @@ -1803,11 +1792,10 @@ prs_haddr(src, htype) report(LOG_ERR, "Add 0x prefix if hex value starts with A-F"); /* OK, assume it must be numeric. */ } -#endif hap = haddr; while (hap < haddr + hal) { - if (*p == '.') + if ((*p == '.') || (*p == ':')) p++; if (interp_byte(&p, hap++) < 0) { return NULL; diff --git a/libexec/bootpd/tools/bootpef/bootpef.c b/libexec/bootpd/tools/bootpef/bootpef.c index eb1893501242..3ffe50be08cb 100644 --- a/libexec/bootpd/tools/bootpef/bootpef.c +++ b/libexec/bootpd/tools/bootpef/bootpef.c @@ -20,11 +20,6 @@ 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 @@ -97,7 +92,6 @@ static char rcsid[] = "$Id: bootpef.c,v 1.1.1.1 1994/09/10 14:44:54 csgr Exp $"; #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)); @@ -291,7 +285,6 @@ mktagfile(hp) FILE *fp; int bytesleft, len; byte *vp; - char *tmpstr; if (!hp->flags.exten_file) return; @@ -332,7 +325,7 @@ mktagfile(hp) } fclose(fp); -} /* dovend_rfc1048 */ +} /* mktagfile */ /* * Local Variables: diff --git a/libexec/bootpd/tools/bootptest/bootptest.c b/libexec/bootpd/tools/bootptest/bootptest.c index bc235ac10650..c4e38d412144 100644 --- a/libexec/bootpd/tools/bootptest/bootptest.c +++ b/libexec/bootpd/tools/bootptest/bootptest.c @@ -40,11 +40,16 @@ char *usage = "bootptest [-h] server-name [vendor-data-template-file]"; #include #include #include +#include #include #include #include /* inet_ntoa */ +#ifndef NO_UNISTD +#include +#endif + #include #include #include @@ -57,8 +62,12 @@ char *usage = "bootptest [-h] server-name [vendor-data-template-file]"; #include "bootp.h" #include "bootptest.h" #include "getif.h" +#include "getether.h" + #include "patchlevel.h" +static void send_request(); + #define LOG_ERR 1 #define BUFLEN 1024 #define WAITSECS 1 @@ -94,10 +103,12 @@ u_char eaddr[16]; /* Ethernet address */ */ int debug = 1; /* Debugging flag (level) */ -char hostname[64]; char *sndbuf; /* Send packet buffer */ char *rcvbuf; /* Receive packet buffer */ +struct utsname my_uname; +char *hostname; + /* * Vendor magic cookies for CMU and RFC1048 */ @@ -114,6 +125,7 @@ extern void bootp_print(); * the receiver loop is started. Die when interrupted. */ +void main(argc, argv) int argc; char **argv; @@ -127,7 +139,7 @@ main(argc, argv) char *bp_file = NULL; int32 server_addr; /* inet addr, network order */ int s; /* Socket file descriptor */ - int n, tolen, fromlen, recvcnt; + int n, fromlen, recvcnt; int use_hwa = 0; int32 vend_magic; int32 xid; @@ -149,6 +161,12 @@ main(argc, argv) */ assert(sizeof(struct bootp) == BP_MINPKTSZ); + if (uname(&my_uname) < 0) { + fprintf(stderr, "%s: can't get hostname\n", argv[0]); + exit(1); + } + hostname = my_uname.nodename; + sndbuf = malloc(BUFLEN); rcvbuf = malloc(BUFLEN); if (!sndbuf || !rcvbuf) { @@ -302,7 +320,7 @@ main(argc, argv) printf("No interface for %s\n", servername); exit(1); } - if (getether(ifr->ifr_name, eaddr)) { + if (getether(ifr->ifr_name, (char*)eaddr)) { printf("Can not get ether addr for %s\n", ifr->ifr_name); exit(1); } @@ -312,7 +330,6 @@ main(argc, argv) 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"); @@ -422,6 +439,7 @@ main(argc, argv) exit(1); } +static void send_request(s) int s; { @@ -451,7 +469,7 @@ printfn(s, ep) register u_char c; putchar('"'); - while (c = *s++) { + while ((c = *s++) != '\0') { if (s > ep) { putchar('"'); return (1); diff --git a/libexec/bootpd/tools/bootptest/print-bootp.c b/libexec/bootpd/tools/bootptest/print-bootp.c index f4169986920a..ff31670a45c9 100644 --- a/libexec/bootpd/tools/bootptest/print-bootp.c +++ b/libexec/bootpd/tools/bootptest/print-bootp.c @@ -23,18 +23,19 @@ * This file was copied from tcpdump-2.1.1 and modified. * There is an e-mail list for tcpdump: */ -#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 New data-driven option print routine. */ -#endif #include #include #include #include + +#ifdef _AIX32 +#include /* for struct timeval in net/if.h */ +#endif #include #include + #include #include @@ -42,6 +43,7 @@ static char rcsid[] = "$Id: print-bootp.c,v 1.1.1.1 1994/09/10 14:44:55 csgr Exp #include "bootptest.h" /* These decode the vendor data. */ +extern int printfn(); static void rfc1048_print(); static void cmu_print(); static void other_print(); @@ -271,8 +273,6 @@ rfc1048_opts[] = { }; #define KNOWN_OPTIONS (sizeof(rfc1048_opts) / sizeof(rfc1048_opts[0])) -static void print_string(); - static void rfc1048_print(bp, length) register u_char *bp; @@ -280,7 +280,7 @@ rfc1048_print(bp, length) { u_char tag; u_char *ep; - register int len, j; + register int len; u_int32 ul; u_short us; struct in_addr ia; @@ -433,7 +433,6 @@ other_print(bp, 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; diff --git a/libexec/bootpd/trygetea.c b/libexec/bootpd/trygetea.c index e9314aede96d..5510995386e9 100644 --- a/libexec/bootpd/trygetea.c +++ b/libexec/bootpd/trygetea.c @@ -9,6 +9,9 @@ #include #endif +#ifdef _AIX32 +#include /* for struct timeval in net/if.h */ +#endif #include /* for struct ifreq */ #include #include /* inet_ntoa */ @@ -18,10 +21,14 @@ #include #include +#include "getether.h" + int debug = 0; char *progname; +void main(argc, argv) + int argc; char **argv; { u_char ea[16]; /* Ethernet address */ @@ -33,7 +40,7 @@ main(argc, argv) printf("need interface name\n"); exit(1); } - if ((i = getether(argv[1], ea)) < 0) { + if ((i = getether(argv[1], (char*)ea)) < 0) { printf("Could not get Ethernet address (rc=%d)\n", i); exit(1); } diff --git a/libexec/bootpd/trygetif.c b/libexec/bootpd/trygetif.c index 894f17b6e917..8c78ee34247a 100644 --- a/libexec/bootpd/trygetif.c +++ b/libexec/bootpd/trygetif.c @@ -9,6 +9,9 @@ #include #endif +#ifdef _AIX32 +#include /* for struct timeval in net/if.h */ +#endif #include /* for struct ifreq */ #include #include /* inet_ntoa */ @@ -23,23 +26,26 @@ int debug = 0; char *progname; +void main(argc, argv) + int argc; 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; + int s; progname = argv[0]; /* for report */ dap = NULL; if (argc > 1) { dap = &dst_addr; - if (inet_aton(argv[1], &dst_addr) == 0) { + 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]); diff --git a/libexec/bootpd/trylook.c b/libexec/bootpd/trylook.c index 40652a21159b..0479166d2f35 100644 --- a/libexec/bootpd/trylook.c +++ b/libexec/bootpd/trylook.c @@ -15,7 +15,9 @@ extern char *inet_ntoa(); int debug = 0; char *progname; +void main(argc, argv) + int argc; char **argv; { int i; @@ -38,12 +40,16 @@ main(argc, argv) printf(" ipa=%s", a); /* Ether addr */ + printf(" hwa="); hwa = lookup_hwa(argv[i], 1); if (!hwa) - a = "?"; - else - a = ether_ntoa(hwa); - printf(" hwa=%s\n", a); + printf("?\n"); + else { + int i; + for (i = 0; i < 6; i++) + printf(":%x", hwa[i] & 0xFF); + putchar('\n'); + } } exit(0);