summaryrefslogtreecommitdiffstats
path: root/libexec
diff options
context:
space:
mode:
authorpst <pst@FreeBSD.org>1996-01-23 01:35:04 +0000
committerpst <pst@FreeBSD.org>1996-01-23 01:35:04 +0000
commitaccc2aa38fbbf04568a6d3941e897dc34aee7930 (patch)
tree9d4d2f644df6a63fbb148e0952fdf7f3ae9aebf5 /libexec
parent6b42e1664561f04b1d3f497ecd5ccad48fd8c3b4 (diff)
downloadFreeBSD-src-accc2aa38fbbf04568a6d3941e897dc34aee7930.zip
FreeBSD-src-accc2aa38fbbf04568a6d3941e897dc34aee7930.tar.gz
Import bootpd-2.4.3 from ftp.mc.com
Diffstat (limited to 'libexec')
-rw-r--r--libexec/bootpd/.indent.pro3
-rw-r--r--libexec/bootpd/Announce3
-rw-r--r--libexec/bootpd/Changes47
-rw-r--r--libexec/bootpd/Makefile.UNIX33
-rw-r--r--libexec/bootpd/Problems18
-rw-r--r--libexec/bootpd/README2
-rw-r--r--libexec/bootpd/ToDo61
-rw-r--r--libexec/bootpd/bootp.h2
-rw-r--r--libexec/bootpd/bootpd.82
-rw-r--r--libexec/bootpd/bootpd.c79
-rw-r--r--libexec/bootpd/bootpgw/bootpgw.c687
-rw-r--r--libexec/bootpd/bootptab.52
-rw-r--r--libexec/bootpd/bootptab.mcs7
-rw-r--r--libexec/bootpd/dovend.c3
-rw-r--r--libexec/bootpd/dumptab.c2
-rw-r--r--libexec/bootpd/getether.c27
-rw-r--r--libexec/bootpd/getether.h7
-rw-r--r--libexec/bootpd/getif.c3
-rw-r--r--libexec/bootpd/hash.c5
-rw-r--r--libexec/bootpd/hwaddr.c113
-rw-r--r--libexec/bootpd/hwaddr.h2
-rw-r--r--libexec/bootpd/lookup.c3
-rw-r--r--libexec/bootpd/patchlevel.h2
-rw-r--r--libexec/bootpd/readfile.c28
-rw-r--r--libexec/bootpd/tools/bootpef/bootpef.c9
-rw-r--r--libexec/bootpd/tools/bootptest/bootptest.c28
-rw-r--r--libexec/bootpd/tools/bootptest/print-bootp.c15
-rw-r--r--libexec/bootpd/trygetea.c9
-rw-r--r--libexec/bootpd/trygetif.c12
-rw-r--r--libexec/bootpd/trylook.c14
30 files changed, 1082 insertions, 146 deletions
diff --git a/libexec/bootpd/.indent.pro b/libexec/bootpd/.indent.pro
new file mode 100644
index 0000000..177ed73
--- /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 e4ae04c..a76e18ac 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 0616548..b08989e 100644
--- a/libexec/bootpd/Changes
+++ b/libexec/bootpd/Changes
@@ -2,6 +2,53 @@ Changes, most recent first
Date, <email> 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 <otto@tukki.jyu.fi>]
+ 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 <ukkonen@csc.fi>
+ Allow bootptab syntax: ha="0:0:c0:80:e8:a7"
+
+11/30/94 Tonny van Lankveld <A.L.M.G.v.Lankveld@urc.tue.nl>
+ 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 <rbm@montrouge.mis.slb.com>
+ 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 e333ce5..701eb2b 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 <sys/sockio.h>, 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 9478676..78d809e 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 <ivan.auger@wadsworth.org>)
+
diff --git a/libexec/bootpd/README b/libexec/bootpd/README
index c7755b7..0901b25 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 0000000..261d24c
--- /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 <dpm@depend.com>
+ * 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
+<middelin@calvin.polyware.iaf.nl> 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 0651aa5..23c0a21 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.8 b/libexec/bootpd/bootpd.8
index 2505593..91048da 100644
--- a/libexec/bootpd/bootpd.8
+++ b/libexec/bootpd/bootpd.8
@@ -1,6 +1,6 @@
.\" 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 $
+.\" $Header: $
.\"
.TH BOOTPD 8 "November 06, 1993" "Carnegie Mellon University"
.SH NAME
diff --git a/libexec/bootpd/bootpd.c b/libexec/bootpd/bootpd.c
index 323132a..745de7e 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/10 14:44:54 csgr Exp $";
-#endif
-
/*
* BOOTP (bootstrap protocol) server daemon.
*
@@ -49,6 +45,7 @@ static char rcsid[] = "$Id: bootpd.c,v 1.1.1.1 1994/09/10 14:44:54 csgr Exp $";
#include <sys/file.h>
#include <sys/time.h>
#include <sys/stat.h>
+#include <sys/utsname.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -57,6 +54,7 @@ static char rcsid[] = "$Id: bootpd.c,v 1.1.1.1 1994/09/10 14:44:54 csgr Exp $";
#ifndef NO_UNISTD
#include <unistd.h>
#endif
+
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
@@ -71,11 +69,6 @@ static char rcsid[] = "$Id: bootpd.c,v 1.1.1.1 1994/09/10 14:44:54 csgr Exp $";
# include <fcntl.h> /* 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 <memory.h>
/* 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";
diff --git a/libexec/bootpd/bootpgw/bootpgw.c b/libexec/bootpd/bootpgw/bootpgw.c
new file mode 100644
index 0000000..353d917
--- /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 <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/utsname.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h> /* inet_ntoa */
+
+#ifndef NO_UNISTD
+#include <unistd.h>
+#endif
+
+#include <stdlib.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <syslog.h>
+#include <assert.h>
+
+#ifdef NO_SETSID
+# include <fcntl.h> /* for O_RDONLY, etc */
+#endif
+
+#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 "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 <walker@zk3.dec.com> 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 7495383..c79116a 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 6fa04d1..2f8b3a6 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 ba6ab28..e46ae9e 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 5893f6c..8c049b9 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 d131b50..a96a4bb 100644
--- a/libexec/bootpd/getether.c
+++ b/libexec/bootpd/getether.c
@@ -11,9 +11,14 @@
#include <sys/types.h>
#include <sys/socket.h>
+#ifndef NO_UNISTD
+#include <unistd.h>
+#endif
+
#include <ctype.h>
#include <syslog.h>
+#include "getether.h"
#include "report.h"
#define EALEN 6
@@ -168,10 +173,12 @@ getether(ifname, eap)
#include <sys/sockio.h>
#include <sys/dlpi.h>
#include <stropts.h>
+#include <string.h>
#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 <nigelm@ohm.york.ac.uk>
+ * written by Nigel Metheringham <nigelm@ohm.york.ac.uk> and
+ * updated by Pauline Middelink <middelin@polyware.iaf.nl>
*
* 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 <memory.h>
#include <sys/ioctl.h>
#include <net/if.h> /* struct ifreq */
+#include <sys/socketio.h> /* 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 <linux/sockios.h> /* 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 0000000..2f98299
--- /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 6cc1649..de9f96d 100644
--- a/libexec/bootpd/getif.c
+++ b/libexec/bootpd/getif.c
@@ -13,6 +13,9 @@
#include <sys/stropts.h>
#endif
+#ifdef _AIX32
+#include <sys/time.h> /* for struct timeval in net/if.h */
+#endif
#include <net/if.h> /* for struct ifreq */
#include <netinet/in.h>
diff --git a/libexec/bootpd/hash.c b/libexec/bootpd/hash.c
index 2ecda63..9637c9a 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 840b953..191fadc 100644
--- a/libexec/bootpd/hwaddr.c
+++ b/libexec/bootpd/hwaddr.c
@@ -17,8 +17,19 @@
#include <fcntl.h>
#endif
+#ifdef _AIX32
+#include <sys/time.h> /* for struct timeval in net/if.h */
+#include <net/if.h> /* for struct ifnet in net/if_arp.h */
+#endif
+
#include <net/if_arp.h>
#include <netinet/in.h>
+
+#ifdef WIN_TCP
+#include <netinet/if_ether.h>
+#include <sys/dlpi.h>
+#endif
+
#include <stdio.h>
#ifndef NO_UNISTD
#include <unistd.h>
@@ -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 <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);
+ {
+ 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 dea7158..8b40799 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 2a30a59..c99f1b8 100644
--- a/libexec/bootpd/lookup.c
+++ b/libexec/bootpd/lookup.c
@@ -5,6 +5,9 @@
#include <sys/types.h>
#include <sys/socket.h>
+#ifdef _AIX32
+#include <sys/time.h> /* for struct timeval in net/if.h */
+#endif
#include <net/if.h>
#include <netinet/in.h>
diff --git a/libexec/bootpd/patchlevel.h b/libexec/bootpd/patchlevel.h
index 782959e..3909c64 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 4a9d993..f7fbdc0 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 eb18935..3ffe50b 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 bc235ac..c4e38d4 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 <sys/file.h>
#include <sys/time.h>
#include <sys/stat.h>
+#include <sys/utsname.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h> /* inet_ntoa */
+#ifndef NO_UNISTD
+#include <unistd.h>
+#endif
+
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
@@ -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 f416998..ff31670 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: <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>
+
+#ifdef _AIX32
+#include <sys/time.h> /* for struct timeval in net/if.h */
+#endif
#include <net/if.h>
#include <netinet/in.h>
+
#include <string.h>
#include <ctype.h>
@@ -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 e9314ae..5510995 100644
--- a/libexec/bootpd/trygetea.c
+++ b/libexec/bootpd/trygetea.c
@@ -9,6 +9,9 @@
#include <sys/sockio.h>
#endif
+#ifdef _AIX32
+#include <sys/time.h> /* for struct timeval in net/if.h */
+#endif
#include <net/if.h> /* for struct ifreq */
#include <netinet/in.h>
#include <arpa/inet.h> /* inet_ntoa */
@@ -18,10 +21,14 @@
#include <ctype.h>
#include <errno.h>
+#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 894f17b..8c78ee3 100644
--- a/libexec/bootpd/trygetif.c
+++ b/libexec/bootpd/trygetif.c
@@ -9,6 +9,9 @@
#include <sys/sockio.h>
#endif
+#ifdef _AIX32
+#include <sys/time.h> /* for struct timeval in net/if.h */
+#endif
#include <net/if.h> /* for struct ifreq */
#include <netinet/in.h>
#include <arpa/inet.h> /* 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 40652a2..0479166 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);
OpenPOWER on IntegriCloud