Original version from 4.4BSD/Utah.
This commit is contained in:
parent
07a07b09a6
commit
e05cab76da
|
@ -0,0 +1,11 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/4/93
|
||||
|
||||
PROG= rbootd
|
||||
SRCS= bpf.c conf.c parseconf.c rbootd.c rmpproto.c utils.c
|
||||
MAN8= rbootd.0
|
||||
|
||||
#afterinstall:
|
||||
# (cd ${.CURDIR}/bootdir && install -c -o ${BINOWN} -g ${BINGRP} \
|
||||
# -m 444 * ${DESTDIR}/usr/mdec/)
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -0,0 +1,422 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)bpf.c 8.1 (Berkeley) 6/4/93
|
||||
*
|
||||
* Utah $Hdr: bpf.c 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)bpf.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/bpf.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include "defs.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
static int BpfFd = -1;
|
||||
static unsigned BpfLen = 0;
|
||||
static u_char *BpfPkt = NULL;
|
||||
|
||||
/*
|
||||
** BpfOpen -- Open and initialize a BPF device.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** File descriptor of opened BPF device (for select() etc).
|
||||
**
|
||||
** Side Effects:
|
||||
** If an error is encountered, the program terminates here.
|
||||
*/
|
||||
int
|
||||
BpfOpen()
|
||||
{
|
||||
struct ifreq ifr;
|
||||
char bpfdev[32];
|
||||
int n = 0;
|
||||
|
||||
/*
|
||||
* Open the first available BPF device.
|
||||
*/
|
||||
do {
|
||||
(void) sprintf(bpfdev, _PATH_BPF, n++);
|
||||
BpfFd = open(bpfdev, O_RDWR);
|
||||
} while (BpfFd < 0 && (errno == EBUSY || errno == EPERM));
|
||||
|
||||
if (BpfFd < 0) {
|
||||
syslog(LOG_ERR, "bpf: no available devices: %m");
|
||||
Exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set interface name for bpf device, get data link layer
|
||||
* type and make sure it's type Ethernet.
|
||||
*/
|
||||
(void) strncpy(ifr.ifr_name, IntfName, sizeof(ifr.ifr_name));
|
||||
if (ioctl(BpfFd, BIOCSETIF, (caddr_t)&ifr) < 0) {
|
||||
syslog(LOG_ERR, "bpf: ioctl(BIOCSETIF,%s): %m", IntfName);
|
||||
Exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure we are dealing with an Ethernet device.
|
||||
*/
|
||||
if (ioctl(BpfFd, BIOCGDLT, (caddr_t)&n) < 0) {
|
||||
syslog(LOG_ERR, "bpf: ioctl(BIOCGDLT): %m");
|
||||
Exit(0);
|
||||
}
|
||||
if (n != DLT_EN10MB) {
|
||||
syslog(LOG_ERR,"bpf: %s: data-link type %d unsupported",
|
||||
IntfName, n);
|
||||
Exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* On read(), return packets immediately (do not buffer them).
|
||||
*/
|
||||
n = 1;
|
||||
if (ioctl(BpfFd, BIOCIMMEDIATE, (caddr_t)&n) < 0) {
|
||||
syslog(LOG_ERR, "bpf: ioctl(BIOCIMMEDIATE): %m");
|
||||
Exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to enable the chip/driver's multicast address filter to
|
||||
* grab our RMP address. If this fails, try promiscuous mode.
|
||||
* If this fails, there's no way we are going to get any RMP
|
||||
* packets so just exit here.
|
||||
*/
|
||||
#ifdef MSG_EOR
|
||||
ifr.ifr_addr.sa_len = RMP_ADDRLEN + 2;
|
||||
#endif
|
||||
ifr.ifr_addr.sa_family = AF_UNSPEC;
|
||||
bcopy(&RmpMcastAddr[0], (char *)&ifr.ifr_addr.sa_data[0], RMP_ADDRLEN);
|
||||
if (ioctl(BpfFd, SIOCADDMULTI, (caddr_t)&ifr) < 0) {
|
||||
syslog(LOG_WARNING,
|
||||
"bpf: can't add mcast addr (%m), setting promiscuous mode");
|
||||
|
||||
if (ioctl(BpfFd, BIOCPROMISC, (caddr_t)0) < 0) {
|
||||
syslog(LOG_ERR, "bpf: can't set promiscuous mode: %m");
|
||||
Exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Ask BPF how much buffer space it requires and allocate one.
|
||||
*/
|
||||
if (ioctl(BpfFd, BIOCGBLEN, (caddr_t)&BpfLen) < 0) {
|
||||
syslog(LOG_ERR, "bpf: ioctl(BIOCGBLEN): %m");
|
||||
Exit(0);
|
||||
}
|
||||
if (BpfPkt == NULL)
|
||||
BpfPkt = (u_char *)malloc(BpfLen);
|
||||
|
||||
if (BpfPkt == NULL) {
|
||||
syslog(LOG_ERR, "bpf: out of memory (%u bytes for bpfpkt)",
|
||||
BpfLen);
|
||||
Exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a little program to snarf RMP Boot packets and stuff
|
||||
* it down BPF's throat (i.e. set up the packet filter).
|
||||
*/
|
||||
{
|
||||
#define RMP ((struct rmp_packet *)0)
|
||||
static struct bpf_insn bpf_insn[] = {
|
||||
{ BPF_LD|BPF_B|BPF_ABS, 0, 0, (long)&RMP->hp_llc.dsap },
|
||||
{ BPF_JMP|BPF_JEQ|BPF_K, 0, 5, IEEE_DSAP_HP },
|
||||
{ BPF_LD|BPF_H|BPF_ABS, 0, 0, (long)&RMP->hp_llc.cntrl },
|
||||
{ BPF_JMP|BPF_JEQ|BPF_K, 0, 3, IEEE_CNTL_HP },
|
||||
{ BPF_LD|BPF_H|BPF_ABS, 0, 0, (long)&RMP->hp_llc.dxsap },
|
||||
{ BPF_JMP|BPF_JEQ|BPF_K, 0, 1, HPEXT_DXSAP },
|
||||
{ BPF_RET|BPF_K, 0, 0, RMP_MAX_PACKET },
|
||||
{ BPF_RET|BPF_K, 0, 0, 0x0 }
|
||||
};
|
||||
#undef RMP
|
||||
static struct bpf_program bpf_pgm = {
|
||||
sizeof(bpf_insn)/sizeof(bpf_insn[0]), bpf_insn
|
||||
};
|
||||
|
||||
if (ioctl(BpfFd, BIOCSETF, (caddr_t)&bpf_pgm) < 0) {
|
||||
syslog(LOG_ERR, "bpf: ioctl(BIOCSETF): %m");
|
||||
Exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
return(BpfFd);
|
||||
}
|
||||
|
||||
/*
|
||||
** BPF GetIntfName -- Return the name of a network interface attached to
|
||||
** the system, or 0 if none can be found. The interface
|
||||
** must be configured up; the lowest unit number is
|
||||
** preferred; loopback is ignored.
|
||||
**
|
||||
** Parameters:
|
||||
** errmsg - if no network interface found, *errmsg explains why.
|
||||
**
|
||||
** Returns:
|
||||
** A (static) pointer to interface name, or NULL on error.
|
||||
**
|
||||
** Side Effects:
|
||||
** None.
|
||||
*/
|
||||
char *
|
||||
BpfGetIntfName(errmsg)
|
||||
char **errmsg;
|
||||
{
|
||||
struct ifreq ibuf[8], *ifrp, *ifend, *mp;
|
||||
struct ifconf ifc;
|
||||
int fd;
|
||||
int minunit, n;
|
||||
char *cp;
|
||||
static char device[sizeof(ifrp->ifr_name)];
|
||||
static char errbuf[128] = "No Error!";
|
||||
|
||||
if (errmsg != NULL)
|
||||
*errmsg = errbuf;
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||
(void) strcpy(errbuf, "bpf: socket: %m");
|
||||
return(NULL);
|
||||
}
|
||||
ifc.ifc_len = sizeof ibuf;
|
||||
ifc.ifc_buf = (caddr_t)ibuf;
|
||||
|
||||
#ifdef OSIOCGIFCONF
|
||||
if (ioctl(fd, OSIOCGIFCONF, (char *)&ifc) < 0 ||
|
||||
ifc.ifc_len < sizeof(struct ifreq)) {
|
||||
(void) strcpy(errbuf, "bpf: ioctl(OSIOCGIFCONF): %m");
|
||||
return(NULL);
|
||||
}
|
||||
#else
|
||||
if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
|
||||
ifc.ifc_len < sizeof(struct ifreq)) {
|
||||
(void) strcpy(errbuf, "bpf: ioctl(SIOCGIFCONF): %m");
|
||||
return(NULL);
|
||||
}
|
||||
#endif
|
||||
ifrp = ibuf;
|
||||
ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
|
||||
|
||||
mp = 0;
|
||||
minunit = 666;
|
||||
for (; ifrp < ifend; ++ifrp) {
|
||||
if (ioctl(fd, SIOCGIFFLAGS, (char *)ifrp) < 0) {
|
||||
(void) strcpy(errbuf, "bpf: ioctl(SIOCGIFFLAGS): %m");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* If interface is down or this is the loopback interface,
|
||||
* ignore it.
|
||||
*/
|
||||
if ((ifrp->ifr_flags & IFF_UP) == 0 ||
|
||||
#ifdef IFF_LOOPBACK
|
||||
(ifrp->ifr_flags & IFF_LOOPBACK))
|
||||
#else
|
||||
(strcmp(ifrp->ifr_name, "lo0") == 0))
|
||||
#endif
|
||||
continue;
|
||||
|
||||
for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp)
|
||||
;
|
||||
n = atoi(cp);
|
||||
if (n < minunit) {
|
||||
minunit = n;
|
||||
mp = ifrp;
|
||||
}
|
||||
}
|
||||
|
||||
(void) close(fd);
|
||||
if (mp == 0) {
|
||||
(void) strcpy(errbuf, "bpf: no interfaces found");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
(void) strcpy(device, mp->ifr_name);
|
||||
return(device);
|
||||
}
|
||||
|
||||
/*
|
||||
** BpfRead -- Read packets from a BPF device and fill in `rconn'.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - filled in with next packet.
|
||||
** doread - is True if we can issue a read() syscall.
|
||||
**
|
||||
** Returns:
|
||||
** True if `rconn' contains a new packet, False otherwise.
|
||||
**
|
||||
** Side Effects:
|
||||
** None.
|
||||
*/
|
||||
int
|
||||
BpfRead(rconn, doread)
|
||||
RMPCONN *rconn;
|
||||
int doread;
|
||||
{
|
||||
register int datlen, caplen, hdrlen;
|
||||
static u_char *bp = NULL, *ep = NULL;
|
||||
int cc;
|
||||
|
||||
/*
|
||||
* The read() may block, or it may return one or more packets.
|
||||
* We let the caller decide whether or not we can issue a read().
|
||||
*/
|
||||
if (doread) {
|
||||
if ((cc = read(BpfFd, (char *)BpfPkt, (int)BpfLen)) < 0) {
|
||||
syslog(LOG_ERR, "bpf: read: %m");
|
||||
return(0);
|
||||
} else {
|
||||
bp = BpfPkt;
|
||||
ep = BpfPkt + cc;
|
||||
}
|
||||
}
|
||||
|
||||
#define bhp ((struct bpf_hdr *)bp)
|
||||
/*
|
||||
* If there is a new packet in the buffer, stuff it into `rconn'
|
||||
* and return a success indication.
|
||||
*/
|
||||
if (bp < ep) {
|
||||
datlen = bhp->bh_datalen;
|
||||
caplen = bhp->bh_caplen;
|
||||
hdrlen = bhp->bh_hdrlen;
|
||||
|
||||
if (caplen != datlen)
|
||||
syslog(LOG_ERR,
|
||||
"bpf: short packet dropped (%d of %d bytes)",
|
||||
caplen, datlen);
|
||||
else if (caplen > sizeof(struct rmp_packet))
|
||||
syslog(LOG_ERR, "bpf: large packet dropped (%d bytes)",
|
||||
caplen);
|
||||
else {
|
||||
rconn->rmplen = caplen;
|
||||
bcopy((char *)&bhp->bh_tstamp, (char *)&rconn->tstamp,
|
||||
sizeof(struct timeval));
|
||||
bcopy((char *)bp + hdrlen, (char *)&rconn->rmp, caplen);
|
||||
}
|
||||
bp += BPF_WORDALIGN(caplen + hdrlen);
|
||||
return(1);
|
||||
}
|
||||
#undef bhp
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
** BpfWrite -- Write packet to BPF device.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - packet to send.
|
||||
**
|
||||
** Returns:
|
||||
** True if write succeeded, False otherwise.
|
||||
**
|
||||
** Side Effects:
|
||||
** None.
|
||||
*/
|
||||
int
|
||||
BpfWrite(rconn)
|
||||
RMPCONN *rconn;
|
||||
{
|
||||
if (write(BpfFd, (char *)&rconn->rmp, rconn->rmplen) < 0) {
|
||||
syslog(LOG_ERR, "write: %s: %m", EnetStr(rconn));
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
** BpfClose -- Close a BPF device.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** None.
|
||||
*/
|
||||
void
|
||||
BpfClose()
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
if (BpfPkt != NULL) {
|
||||
free((char *)BpfPkt);
|
||||
BpfPkt = NULL;
|
||||
}
|
||||
|
||||
if (BpfFd == -1)
|
||||
return;
|
||||
|
||||
#ifdef MSG_EOR
|
||||
ifr.ifr_addr.sa_len = RMP_ADDRLEN + 2;
|
||||
#endif
|
||||
ifr.ifr_addr.sa_family = AF_UNSPEC;
|
||||
bcopy(&RmpMcastAddr[0], (char *)&ifr.ifr_addr.sa_data[0], RMP_ADDRLEN);
|
||||
if (ioctl(BpfFd, SIOCDELMULTI, (caddr_t)&ifr) < 0)
|
||||
(void) ioctl(BpfFd, BIOCPROMISC, (caddr_t)0);
|
||||
|
||||
(void) close(BpfFd);
|
||||
BpfFd = -1;
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)conf.c 8.1 (Berkeley) 6/4/93
|
||||
*
|
||||
* Utah $Hdr: conf.c 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)conf.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include "defs.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
/*
|
||||
** Define (and possibly initialize) global variables here.
|
||||
**
|
||||
** Caveat:
|
||||
** The maximum number of bootable files (`char *BootFiles[]') is
|
||||
** limited to C_MAXFILE (i.e. the maximum number of files that
|
||||
** can be spec'd in the configuration file). This was done to
|
||||
** simplify the boot file search code.
|
||||
*/
|
||||
|
||||
char *ProgName; /* path-stripped argv[0] */
|
||||
char MyHost[MAXHOSTNAMELEN+1]; /* host name */
|
||||
int MyPid; /* process id */
|
||||
int DebugFlg = 0; /* set true if debugging */
|
||||
int BootAny = 0; /* set true if we boot anyone */
|
||||
|
||||
char *ConfigFile = NULL; /* configuration file */
|
||||
char *DfltConfig = _PATH_RBOOTDCONF; /* default configuration file */
|
||||
char *PidFile = _PATH_RBOOTDPID; /* file w/pid of server */
|
||||
char *BootDir = _PATH_RBOOTDLIB; /* directory w/boot files */
|
||||
char *DbgFile = _PATH_RBOOTDDBG; /* debug output file */
|
||||
|
||||
FILE *DbgFp = NULL; /* debug file pointer */
|
||||
char *IntfName = NULL; /* intf we are attached to */
|
||||
|
||||
u_short SessionID = 0; /* generated session ID */
|
||||
|
||||
char *BootFiles[C_MAXFILE]; /* list of boot files */
|
||||
|
||||
CLIENT *Clients = NULL; /* list of addrs we'll accept */
|
||||
RMPCONN *RmpConns = NULL; /* list of active connections */
|
||||
|
||||
char RmpMcastAddr[RMP_ADDRLEN] = RMP_ADDR; /* RMP multicast address */
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)defs.h 8.1 (Berkeley) 6/4/93
|
||||
*
|
||||
* Utah $Hdr: defs.h 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
#include "rmp.h"
|
||||
#include "rmp_var.h"
|
||||
|
||||
/*
|
||||
** Common #define's and external variables. All other files should
|
||||
** include this.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This may be defined in <sys/param.h>, if not, it's defined here.
|
||||
*/
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 64
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SIGUSR1 and SIGUSR2 are defined in <signal.h> for 4.3BSD systems.
|
||||
*/
|
||||
#ifndef SIGUSR1
|
||||
#define SIGUSR1 SIGEMT
|
||||
#endif
|
||||
#ifndef SIGUSR2
|
||||
#define SIGUSR2 SIGFPE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These can be faster & more efficient than strcmp()/strncmp()...
|
||||
*/
|
||||
#define STREQN(s1,s2) ((*s1 == *s2) && (strcmp(s1,s2) == 0))
|
||||
#define STRNEQN(s1,s2,n) ((*s1 == *s2) && (strncmp(s1,s2,n) == 0))
|
||||
|
||||
/*
|
||||
* Configuration file limitations.
|
||||
*/
|
||||
#define C_MAXFILE 10 /* max number of boot-able files */
|
||||
#define C_LINELEN 1024 /* max length of line */
|
||||
|
||||
/*
|
||||
* Direction of packet (used as argument to DispPkt).
|
||||
*/
|
||||
#define DIR_RCVD 0
|
||||
#define DIR_SENT 1
|
||||
#define DIR_NONE 2
|
||||
|
||||
/*
|
||||
* These need not be functions, so...
|
||||
*/
|
||||
#define FreeStr(str) free(str)
|
||||
#define FreeClient(cli) free(cli)
|
||||
#define GenSessID() (++SessionID ? SessionID: ++SessionID)
|
||||
|
||||
/*
|
||||
* Converting an Ethernet address to a string is done in many routines.
|
||||
* Using `rmp.hp_hdr.saddr' works because this field is *never* changed;
|
||||
* it will *always* contain the source address of the packet.
|
||||
*/
|
||||
#define EnetStr(rptr) GetEtherAddr(&(rptr)->rmp.hp_hdr.saddr[0])
|
||||
|
||||
/*
|
||||
* Every machine we can boot will have one of these allocated for it
|
||||
* (unless there are no restrictions on who we can boot).
|
||||
*/
|
||||
typedef struct client_s {
|
||||
u_char addr[RMP_ADDRLEN]; /* addr of machine */
|
||||
char *files[C_MAXFILE]; /* boot-able files */
|
||||
struct client_s *next; /* ptr to next */
|
||||
} CLIENT;
|
||||
|
||||
/*
|
||||
* Every active connection has one of these allocated for it.
|
||||
*/
|
||||
typedef struct rmpconn_s {
|
||||
struct rmp_packet rmp; /* RMP packet */
|
||||
int rmplen; /* length of packet */
|
||||
struct timeval tstamp; /* last time active */
|
||||
int bootfd; /* open boot file */
|
||||
struct rmpconn_s *next; /* ptr to next */
|
||||
} RMPCONN;
|
||||
|
||||
/*
|
||||
* All these variables are defined in "conf.c".
|
||||
*/
|
||||
extern char *ProgName; /* path-stripped argv[0] */
|
||||
extern char MyHost[]; /* this hosts' name */
|
||||
extern int MyPid; /* this processes' ID */
|
||||
extern int DebugFlg; /* set true if debugging */
|
||||
extern int BootAny; /* set true if we can boot anyone */
|
||||
|
||||
extern char *ConfigFile; /* configuration file */
|
||||
extern char *DfltConfig; /* default configuration file */
|
||||
extern char *DbgFile; /* debug output file */
|
||||
extern char *PidFile; /* file containing pid of server */
|
||||
extern char *BootDir; /* directory w/boot files */
|
||||
|
||||
extern FILE *DbgFp; /* debug file pointer */
|
||||
extern char *IntfName; /* interface we are attached to */
|
||||
|
||||
extern u_short SessionID; /* generated session ID */
|
||||
|
||||
extern char *BootFiles[]; /* list of boot files */
|
||||
|
||||
extern CLIENT *Clients; /* list of addrs we'll accept */
|
||||
extern RMPCONN *RmpConns; /* list of active connections */
|
||||
|
||||
extern char RmpMcastAddr[]; /* RMP multicast address */
|
||||
|
||||
void AddConn __P((RMPCONN *));
|
||||
int BootDone __P((RMPCONN *));
|
||||
void BpfClose __P((void));
|
||||
char *BpfGetIntfName __P((char **));
|
||||
int BpfOpen __P((void));
|
||||
int BpfRead __P((RMPCONN *, int));
|
||||
int BpfWrite __P((RMPCONN *));
|
||||
void DebugOff __P((int));
|
||||
void DebugOn __P((int));
|
||||
void DispPkt __P((RMPCONN *, int));
|
||||
void DoTimeout __P((void));
|
||||
void DspFlnm __P((u_int, char *));
|
||||
void Exit __P((int));
|
||||
CLIENT *FindClient __P((RMPCONN *));
|
||||
RMPCONN *FindConn __P((RMPCONN *));
|
||||
void FreeClients __P((void));
|
||||
void FreeConn __P((RMPCONN *));
|
||||
void FreeConns __P((void));
|
||||
int GetBootFiles __P((void));
|
||||
char *GetEtherAddr __P((u_char *));
|
||||
CLIENT *NewClient __P((u_char *));
|
||||
RMPCONN *NewConn __P((RMPCONN *));
|
||||
char *NewStr __P((char *));
|
||||
u_char *ParseAddr __P((char *));
|
||||
int ParseConfig __P((void));
|
||||
void ProcessPacket __P((RMPCONN *, CLIENT *));
|
||||
void ReConfig __P((int));
|
||||
void RemoveConn __P((RMPCONN *));
|
||||
int SendBootRepl __P((struct rmp_packet *, RMPCONN *, char *[]));
|
||||
int SendFileNo __P((struct rmp_packet *, RMPCONN *, char *[]));
|
||||
int SendPacket __P((RMPCONN *));
|
||||
int SendReadRepl __P((RMPCONN *));
|
||||
int SendServerID __P((RMPCONN *));
|
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)parseconf.c 8.1 (Berkeley) 6/4/93
|
||||
*
|
||||
* Utah $Hdr: parseconf.c 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)parseconf.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include "defs.h"
|
||||
|
||||
/*
|
||||
** ParseConfig -- parse the config file into linked list of clients.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** 1 on success, 0 otherwise.
|
||||
**
|
||||
** Side Effects:
|
||||
** - Linked list of clients will be (re)allocated.
|
||||
**
|
||||
** Warnings:
|
||||
** - GetBootFiles() must be called before this routine
|
||||
** to create a linked list of default boot files.
|
||||
*/
|
||||
int
|
||||
ParseConfig()
|
||||
{
|
||||
FILE *fp;
|
||||
CLIENT *client;
|
||||
u_char *addr;
|
||||
char line[C_LINELEN];
|
||||
register char *cp, *bcp;
|
||||
register int i, j;
|
||||
int omask, linecnt = 0;
|
||||
|
||||
if (BootAny) /* ignore config file */
|
||||
return(1);
|
||||
|
||||
FreeClients(); /* delete old list of clients */
|
||||
|
||||
if ((fp = fopen(ConfigFile, "r")) == NULL) {
|
||||
syslog(LOG_ERR, "ParseConfig: can't open config file (%s)",
|
||||
ConfigFile);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* We've got to block SIGHUP to prevent reconfiguration while
|
||||
* dealing with the linked list of Clients. This can be done
|
||||
* when actually linking the new client into the list, but
|
||||
* this could have unexpected results if the server was HUP'd
|
||||
* whilst reconfiguring. Hence, it is done here.
|
||||
*/
|
||||
omask = sigblock(sigmask(SIGHUP));
|
||||
|
||||
/*
|
||||
* GETSTR positions `bcp' at the start of the current token,
|
||||
* and null terminates it. `cp' is positioned at the start
|
||||
* of the next token. spaces & commas are separators.
|
||||
*/
|
||||
#define GETSTR while (isspace(*cp) || *cp == ',') cp++; \
|
||||
bcp = cp; \
|
||||
while (*cp && *cp!=',' && !isspace(*cp)) cp++; \
|
||||
if (*cp) *cp++ = '\0'
|
||||
|
||||
/*
|
||||
* For each line, parse it into a new CLIENT struct.
|
||||
*/
|
||||
while (fgets(line, C_LINELEN, fp) != NULL) {
|
||||
linecnt++; /* line counter */
|
||||
|
||||
if (*line == '\0' || *line == '#') /* ignore comment */
|
||||
continue;
|
||||
|
||||
if ((cp = index(line,'#')) != NULL) /* trash comments */
|
||||
*cp = '\0';
|
||||
|
||||
cp = line; /* init `cp' */
|
||||
GETSTR; /* get RMP addr */
|
||||
if (bcp == cp) /* all delimiters */
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Get an RMP address from a string. Abort on failure.
|
||||
*/
|
||||
if ((addr = ParseAddr(bcp)) == NULL) {
|
||||
syslog(LOG_ERR,
|
||||
"ParseConfig: line %d: cant parse <%s>",
|
||||
linecnt, bcp);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((client = NewClient(addr)) == NULL) /* alloc new client */
|
||||
continue;
|
||||
|
||||
GETSTR; /* get first file */
|
||||
|
||||
/*
|
||||
* If no boot files are spec'd, use the default list.
|
||||
* Otherwise, validate each file (`bcp') against the
|
||||
* list of boot-able files.
|
||||
*/
|
||||
i = 0;
|
||||
if (bcp == cp) /* no files spec'd */
|
||||
for (; i < C_MAXFILE && BootFiles[i] != NULL; i++)
|
||||
client->files[i] = BootFiles[i];
|
||||
else {
|
||||
do {
|
||||
/*
|
||||
* For each boot file spec'd, make sure it's
|
||||
* in our list. If so, include a pointer to
|
||||
* it in the CLIENT's list of boot files.
|
||||
*/
|
||||
for (j = 0; ; j++) {
|
||||
if (j==C_MAXFILE||BootFiles[j]==NULL) {
|
||||
syslog(LOG_ERR, "ParseConfig: line %d: no boot file (%s)",
|
||||
linecnt, bcp);
|
||||
break;
|
||||
}
|
||||
if (STREQN(BootFiles[j], bcp)) {
|
||||
if (i < C_MAXFILE)
|
||||
client->files[i++] =
|
||||
BootFiles[j];
|
||||
else
|
||||
syslog(LOG_ERR, "ParseConfig: line %d: too many boot files (%s)",
|
||||
linecnt, bcp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
GETSTR; /* get next file */
|
||||
} while (bcp != cp);
|
||||
|
||||
/*
|
||||
* Restricted list of boot files were spec'd,
|
||||
* however, none of them were found. Since we
|
||||
* apparently cant let them boot "just anything",
|
||||
* the entire record is invalidated.
|
||||
*/
|
||||
if (i == 0) {
|
||||
FreeClient(client);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Link this client into the linked list of clients.
|
||||
* SIGHUP has already been blocked.
|
||||
*/
|
||||
if (Clients)
|
||||
client->next = Clients;
|
||||
Clients = client;
|
||||
}
|
||||
|
||||
(void) fclose(fp); /* close config file */
|
||||
|
||||
(void) sigsetmask(omask); /* reset signal mask */
|
||||
|
||||
return(1); /* return success */
|
||||
}
|
||||
|
||||
/*
|
||||
** ParseAddr -- Parse a string containing an RMP address.
|
||||
**
|
||||
** This routine is fairly liberal at parsing an RMP address. The
|
||||
** address must contain 6 octets consisting of between 0 and 2 hex
|
||||
** chars (upper/lower case) separated by colons. If two colons are
|
||||
** together (e.g. "::", the octet between them is recorded as being
|
||||
** zero. Hence, the following addrs are all valid and parse to the
|
||||
** same thing:
|
||||
**
|
||||
** 08:00:09:00:66:ad 8::9:0:66:AD 8::9::66:aD
|
||||
**
|
||||
** For clarity, an RMP address is really an Ethernet address, but
|
||||
** since the HP boot code uses IEEE 802.3, it's really an IEEE
|
||||
** 802.3 address. Of course, all of these are identical.
|
||||
**
|
||||
** Parameters:
|
||||
** str - string representation of an RMP address.
|
||||
**
|
||||
** Returns:
|
||||
** pointer to a static array of RMP_ADDRLEN bytes.
|
||||
**
|
||||
** Side Effects:
|
||||
** None.
|
||||
**
|
||||
** Warnings:
|
||||
** - The return value points to a static buffer; it must
|
||||
** be copied if it's to be saved.
|
||||
** - For speed, we assume a u_char consists of 8 bits.
|
||||
*/
|
||||
u_char *
|
||||
ParseAddr(str)
|
||||
char *str;
|
||||
{
|
||||
static u_char addr[RMP_ADDRLEN];
|
||||
register char *cp;
|
||||
register unsigned i;
|
||||
register int part, subpart;
|
||||
|
||||
bzero((char *)&addr[0], RMP_ADDRLEN); /* zero static buffer */
|
||||
|
||||
part = subpart = 0;
|
||||
for (cp = str; *cp; cp++) {
|
||||
/*
|
||||
* A colon (`:') must be used to delimit each octet.
|
||||
*/
|
||||
if (*cp == ':') {
|
||||
if (++part == RMP_ADDRLEN) /* too many parts */
|
||||
return(NULL);
|
||||
subpart = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert hex character to an integer.
|
||||
*/
|
||||
if (isdigit(*cp))
|
||||
i = *cp - '0';
|
||||
else {
|
||||
i = (isupper(*cp)? tolower(*cp): *cp) - 'a' + 10;
|
||||
if (i < 10 || i > 15) /* not a hex char */
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (subpart++) {
|
||||
if (subpart > 2) /* too many hex chars */
|
||||
return(NULL);
|
||||
addr[part] <<= 4;
|
||||
}
|
||||
addr[part] |= i;
|
||||
}
|
||||
|
||||
if (part != (RMP_ADDRLEN-1)) /* too few parts */
|
||||
return(NULL);
|
||||
|
||||
return(&addr[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
** GetBootFiles -- record list of files in current (boot) directory.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** Number of boot files on success, 0 on failure.
|
||||
**
|
||||
** Side Effects:
|
||||
** Strings in `BootFiles' are freed/allocated.
|
||||
**
|
||||
** Warnings:
|
||||
** - After this routine is called, ParseConfig() must be
|
||||
** called to re-order it's list of boot file pointers.
|
||||
*/
|
||||
int
|
||||
GetBootFiles()
|
||||
{
|
||||
DIR *dfd;
|
||||
struct stat statb;
|
||||
register struct dirent *dp;
|
||||
register int i;
|
||||
|
||||
/*
|
||||
* Free the current list of boot files.
|
||||
*/
|
||||
for (i = 0; i < C_MAXFILE && BootFiles[i] != NULL; i++) {
|
||||
FreeStr(BootFiles[i]);
|
||||
BootFiles[i] = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open current directory to read boot file names.
|
||||
*/
|
||||
if ((dfd = opendir(".")) == NULL) { /* open BootDir */
|
||||
syslog(LOG_ERR, "GetBootFiles: can't open directory (%s)\n",
|
||||
BootDir);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read each boot file name and allocate space for it in the
|
||||
* list of boot files (BootFiles). All boot files read after
|
||||
* C_MAXFILE will be ignored.
|
||||
*/
|
||||
i = 0;
|
||||
for (dp = readdir(dfd); dp != NULL; dp = readdir(dfd)) {
|
||||
if (stat(dp->d_name, &statb) < 0 ||
|
||||
(statb.st_mode & S_IFMT) != S_IFREG)
|
||||
continue;
|
||||
if (i == C_MAXFILE)
|
||||
syslog(LOG_ERR,
|
||||
"GetBootFiles: too many boot files (%s ignored)",
|
||||
dp->d_name);
|
||||
else if ((BootFiles[i] = NewStr(dp->d_name)) != NULL)
|
||||
i++;
|
||||
}
|
||||
|
||||
(void) closedir(dfd); /* close BootDir */
|
||||
|
||||
if (i == 0) /* cant find any boot files */
|
||||
syslog(LOG_ERR, "GetBootFiles: no boot files (%s)\n", BootDir);
|
||||
|
||||
return(i);
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pathnames.h 8.1 (Berkeley) 6/4/93
|
||||
*
|
||||
* Utah $Hdr: pathnames.h 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
#define _PATH_BPF "/dev/bpf%d"
|
||||
#define _PATH_RBOOTDCONF "/etc/rbootd.conf"
|
||||
#define _PATH_RBOOTDDBG "/tmp/rbootd.dbg"
|
||||
#define _PATH_RBOOTDLIB "/usr/mdec/rbootd"
|
||||
#define _PATH_RBOOTDPID "/var/run/rbootd.pid"
|
|
@ -0,0 +1,156 @@
|
|||
.\" Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
.\" for Software Science (CSS).
|
||||
.\" Copyright (c) 1992, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to Berkeley by
|
||||
.\" the Center for Software Science of the University of Utah Computer
|
||||
.\" Science Department. CSS requests users of this software to return
|
||||
.\" to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
.\" CSS redistribution rights.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)rbootd.8 8.2 (Berkeley) 12/11/93
|
||||
.\"
|
||||
.\" Utah $Hdr: rbootd.man 3.1 92/07/06$
|
||||
.\" Author: Jeff Forys, University of Utah CSS
|
||||
.\"
|
||||
.Dd "December 11, 1993"
|
||||
.Dt RBOOTD 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm rbootd
|
||||
.Nd HP remote boot server
|
||||
.Sh SYNOPSIS
|
||||
.Nm rbootd
|
||||
.Op Fl ad
|
||||
.Op Fl i Ar interface
|
||||
.Op config_file
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm rbootd
|
||||
utility services boot requests from Hewlett-Packard workstations over a
|
||||
local area network.
|
||||
All boot files must reside in the boot file directory; further, if a
|
||||
client supplies path information in its boot request, it will be silently
|
||||
stripped away before processing.
|
||||
By default,
|
||||
.Nm rbootd
|
||||
only responds to requests from machines listed in its configuration file.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Fl
|
||||
.It Fl a
|
||||
Respond to boot requests from any machine.
|
||||
The configuration file is ignored if this option is specified.
|
||||
.It Fl d
|
||||
Run
|
||||
.Nm rbootd
|
||||
in debug mode.
|
||||
Packets sent and received are displayed to the terminal.
|
||||
.It Fl i Ar interface
|
||||
Service boot requests on specified interface.
|
||||
If unspecified,
|
||||
.Nm rbootd
|
||||
searches the system interface list for the lowest numbered, configured
|
||||
``up'' interface (excluding loopback).
|
||||
Ties are broken by choosing the earliest match.
|
||||
.El
|
||||
.Pp
|
||||
Specifying
|
||||
.Ar config_file
|
||||
on the command line causes
|
||||
.Nm rbootd
|
||||
to use a different configuration file from the default.
|
||||
.Pp
|
||||
The configuration file is a text file where each line describes a particular
|
||||
machine.
|
||||
A line must start with a machine's Ethernet address followed by an optional
|
||||
list of boot file names.
|
||||
An Ethernet address is specified in hexadecimal with each of its six octets
|
||||
separated by a colon.
|
||||
The boot file names come from the boot file directory.
|
||||
The ethernet address and boot file(s) must be separated by white-space
|
||||
and/or comma characters.
|
||||
A pound sign causes the remainder of a line to be ignored.
|
||||
.Pp
|
||||
Here is a sample configuration file:
|
||||
.Bl -column 08:00:09:0:66:ad SYSHPBSD,SYSHPUX "# vandy (anything)"
|
||||
.It #
|
||||
.It # ethernet addr boot file(s) comments
|
||||
.It #
|
||||
.It 08:00:09:0:66:ad SYSHPBSD # snake (4.3BSD)
|
||||
.It 08:00:09:0:59:5b # vandy (anything)
|
||||
.It 8::9:1:C6:75 SYSHPBSD,SYSHPUX # jaguar (either)
|
||||
.El
|
||||
.Pp
|
||||
.Nm Rbootd
|
||||
logs status and error messages via
|
||||
.Xr syslog 3 .
|
||||
A startup message is always logged, and in the case of fatal errors (or
|
||||
deadly signals) a message is logged announcing the server's termination.
|
||||
In general, a non-fatal error is handled by ignoring the event that caused
|
||||
it (e.g. an invalid Ethernet address in the config file causes that line
|
||||
to be invalidated).
|
||||
.Pp
|
||||
The following signals have the specified effect when sent to the server
|
||||
process using the
|
||||
.Xr kill 1
|
||||
command:
|
||||
.Bl -tag -width SIGUSR1 -offset -compact
|
||||
.It SIGHUP
|
||||
Drop all active connections and reconfigure.
|
||||
.It SIGUSR1
|
||||
Turn on debugging, do nothing if already on.
|
||||
.It SIGUSR2
|
||||
Turn off debugging, do nothing if already off.
|
||||
.El
|
||||
.Sh "FILES"
|
||||
.Bl -tag -width /usr/libexec/rbootd -compact
|
||||
.It /dev/bpf#
|
||||
packet-filter device
|
||||
.It /etc/rbootd.conf
|
||||
configuration file
|
||||
.It /tmp/rbootd.dbg
|
||||
debug output
|
||||
.It /usr/mdec/rbootd
|
||||
directory containing boot files
|
||||
.It /var/run/rbootd.pid
|
||||
process id
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr kill 1 ,
|
||||
.Xr socket 2 ,
|
||||
.Xr signal 3 ,
|
||||
.Xr syslog 3 ,
|
||||
.Xr rmp 4
|
||||
.Sh BUGS
|
||||
If multiple servers are started on the same interface, each will receive
|
||||
and respond to the same boot packets.
|
|
@ -0,0 +1,507 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)rbootd.c 8.1 (Berkeley) 6/4/93
|
||||
*
|
||||
* Utah $Hdr: rbootd.c 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1992, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)rbootd.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include "defs.h"
|
||||
|
||||
|
||||
/* fd mask macros (backward compatibility with 4.2BSD) */
|
||||
#ifndef FD_SET
|
||||
#ifdef notdef
|
||||
typedef struct fd_set { /* this should already be in 4.2 */
|
||||
int fds_bits[1];
|
||||
} fd_set;
|
||||
#endif
|
||||
#define FD_ZERO(p) ((p)->fds_bits[0] = 0)
|
||||
#define FD_SET(n, p) ((p)->fds_bits[0] |= (1 << (n)))
|
||||
#define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1 << (n)))
|
||||
#define FD_ISSET(n, p) ((p)->fds_bits[0] & (1 << (n)))
|
||||
#endif
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int c, fd, omask, maxfds;
|
||||
fd_set rset;
|
||||
|
||||
/*
|
||||
* Find what name we are running under.
|
||||
*/
|
||||
ProgName = (ProgName = rindex(argv[0],'/')) ? ++ProgName : *argv;
|
||||
|
||||
/*
|
||||
* Close any open file descriptors.
|
||||
* Temporarily leave stdin & stdout open for `-d',
|
||||
* and stderr open for any pre-syslog error messages.
|
||||
*/
|
||||
{
|
||||
int i, nfds = getdtablesize();
|
||||
|
||||
for (i = 0; i < nfds; i++)
|
||||
if (i != fileno(stdin) && i != fileno(stdout) &&
|
||||
i != fileno(stderr))
|
||||
(void) close(i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse any arguments.
|
||||
*/
|
||||
while ((c = getopt(argc, argv, "adi:")) != EOF)
|
||||
switch(c) {
|
||||
case 'a':
|
||||
BootAny++;
|
||||
break;
|
||||
case 'd':
|
||||
DebugFlg++;
|
||||
break;
|
||||
case 'i':
|
||||
IntfName = optarg;
|
||||
break;
|
||||
}
|
||||
for (; optind < argc; optind++) {
|
||||
if (ConfigFile == NULL)
|
||||
ConfigFile = argv[optind];
|
||||
else {
|
||||
fprintf(stderr,
|
||||
"%s: too many config files (`%s' ignored)\n",
|
||||
ProgName, argv[optind]);
|
||||
}
|
||||
}
|
||||
|
||||
if (ConfigFile == NULL) /* use default config file */
|
||||
ConfigFile = DfltConfig;
|
||||
|
||||
if (DebugFlg) {
|
||||
DbgFp = stdout; /* output to stdout */
|
||||
|
||||
(void) signal(SIGUSR1, SIG_IGN); /* dont muck w/DbgFp */
|
||||
(void) signal(SIGUSR2, SIG_IGN);
|
||||
} else {
|
||||
(void) fclose(stdin); /* dont need these */
|
||||
(void) fclose(stdout);
|
||||
|
||||
/*
|
||||
* Fork off a child to do the work & exit.
|
||||
*/
|
||||
switch(fork()) {
|
||||
case -1: /* fork failed */
|
||||
fprintf(stderr, "%s: ", ProgName);
|
||||
perror("fork");
|
||||
Exit(0);
|
||||
case 0: /* this is the CHILD */
|
||||
break;
|
||||
default: /* this is the PARENT */
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to disassociate from the current tty.
|
||||
*/
|
||||
{
|
||||
char *devtty = "/dev/tty";
|
||||
int i;
|
||||
|
||||
if ((i = open(devtty, O_RDWR)) < 0) {
|
||||
/* probably already disassociated */
|
||||
if (setpgrp(0, 0) < 0) {
|
||||
fprintf(stderr, "%s: ", ProgName);
|
||||
perror("setpgrp");
|
||||
}
|
||||
} else {
|
||||
if (ioctl(i, (u_long)TIOCNOTTY, (char *)0) < 0){
|
||||
fprintf(stderr, "%s: ", ProgName);
|
||||
perror("ioctl");
|
||||
}
|
||||
(void) close(i);
|
||||
}
|
||||
}
|
||||
|
||||
(void) signal(SIGUSR1, DebugOn);
|
||||
(void) signal(SIGUSR2, DebugOff);
|
||||
}
|
||||
|
||||
(void) fclose(stderr); /* finished with it */
|
||||
|
||||
#ifdef SYSLOG4_2
|
||||
openlog(ProgName, LOG_PID);
|
||||
#else
|
||||
openlog(ProgName, LOG_PID, LOG_DAEMON);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If no interface was specified, get one now.
|
||||
*
|
||||
* This is convoluted because we want to get the default interface
|
||||
* name for the syslog("restarted") message. If BpfGetIntfName()
|
||||
* runs into an error, it will return a syslog-able error message
|
||||
* (in `errmsg') which will be displayed here.
|
||||
*/
|
||||
if (IntfName == NULL) {
|
||||
char *errmsg;
|
||||
|
||||
if ((IntfName = BpfGetIntfName(&errmsg)) == NULL) {
|
||||
syslog(LOG_NOTICE, "restarted (??)");
|
||||
syslog(LOG_ERR, errmsg);
|
||||
Exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
syslog(LOG_NOTICE, "restarted (%s)", IntfName);
|
||||
|
||||
(void) signal(SIGHUP, ReConfig);
|
||||
(void) signal(SIGINT, Exit);
|
||||
(void) signal(SIGTERM, Exit);
|
||||
|
||||
/*
|
||||
* Grab our host name and pid.
|
||||
*/
|
||||
if (gethostname(MyHost, MAXHOSTNAMELEN) < 0) {
|
||||
syslog(LOG_ERR, "gethostname: %m");
|
||||
Exit(0);
|
||||
}
|
||||
MyHost[MAXHOSTNAMELEN] = '\0';
|
||||
|
||||
MyPid = getpid();
|
||||
|
||||
/*
|
||||
* Write proc's pid to a file.
|
||||
*/
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = fopen(PidFile, "w")) != NULL) {
|
||||
(void) fprintf(fp, "%d\n", MyPid);
|
||||
(void) fclose(fp);
|
||||
} else {
|
||||
syslog(LOG_WARNING, "fopen: failed (%s)", PidFile);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* All boot files are relative to the boot directory, we might
|
||||
* as well chdir() there to make life easier.
|
||||
*/
|
||||
if (chdir(BootDir) < 0) {
|
||||
syslog(LOG_ERR, "chdir: %m (%s)", BootDir);
|
||||
Exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initial configuration.
|
||||
*/
|
||||
omask = sigblock(sigmask(SIGHUP)); /* prevent reconfig's */
|
||||
if (GetBootFiles() == 0) /* get list of boot files */
|
||||
Exit(0);
|
||||
if (ParseConfig() == 0) /* parse config file */
|
||||
Exit(0);
|
||||
|
||||
/*
|
||||
* Open and initialize a BPF device for the appropriate interface.
|
||||
* If an error is encountered, a message is displayed and Exit()
|
||||
* is called.
|
||||
*/
|
||||
fd = BpfOpen();
|
||||
|
||||
(void) sigsetmask(omask); /* allow reconfig's */
|
||||
|
||||
/*
|
||||
* Main loop: receive a packet, determine where it came from,
|
||||
* and if we service this host, call routine to handle request.
|
||||
*/
|
||||
maxfds = fd + 1;
|
||||
FD_ZERO(&rset);
|
||||
FD_SET(fd, &rset);
|
||||
for (;;) {
|
||||
struct timeval timeout;
|
||||
fd_set r;
|
||||
int nsel;
|
||||
|
||||
r = rset;
|
||||
|
||||
if (RmpConns == NULL) { /* timeout isnt necessary */
|
||||
nsel = select(maxfds, &r, (fd_set *)0, (fd_set *)0,
|
||||
(struct timeval *)0);
|
||||
} else {
|
||||
timeout.tv_sec = RMP_TIMEOUT;
|
||||
timeout.tv_usec = 0;
|
||||
nsel = select(maxfds, &r, (fd_set *)0, (fd_set *)0,
|
||||
&timeout);
|
||||
}
|
||||
|
||||
if (nsel < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
syslog(LOG_ERR, "select: %m");
|
||||
Exit(0);
|
||||
} else if (nsel == 0) { /* timeout */
|
||||
DoTimeout(); /* clear stale conns */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FD_ISSET(fd, &r)) {
|
||||
RMPCONN rconn;
|
||||
CLIENT *client, *FindClient();
|
||||
int doread = 1;
|
||||
|
||||
while (BpfRead(&rconn, doread)) {
|
||||
doread = 0;
|
||||
|
||||
if (DbgFp != NULL) /* display packet */
|
||||
DispPkt(&rconn,DIR_RCVD);
|
||||
|
||||
omask = sigblock(sigmask(SIGHUP));
|
||||
|
||||
/*
|
||||
* If we do not restrict service, set the
|
||||
* client to NULL (ProcessPacket() handles
|
||||
* this). Otherwise, check that we can
|
||||
* service this host; if not, log a message
|
||||
* and ignore the packet.
|
||||
*/
|
||||
if (BootAny) {
|
||||
client = NULL;
|
||||
} else if ((client=FindClient(&rconn))==NULL) {
|
||||
syslog(LOG_INFO,
|
||||
"%s: boot packet ignored",
|
||||
EnetStr(&rconn));
|
||||
(void) sigsetmask(omask);
|
||||
continue;
|
||||
}
|
||||
|
||||
ProcessPacket(&rconn,client);
|
||||
|
||||
(void) sigsetmask(omask);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** DoTimeout -- Free any connections that have timed out.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - Timed out connections in `RmpConns' will be freed.
|
||||
*/
|
||||
void
|
||||
DoTimeout()
|
||||
{
|
||||
register RMPCONN *rtmp;
|
||||
struct timeval now;
|
||||
|
||||
(void) gettimeofday(&now, (struct timezone *)0);
|
||||
|
||||
/*
|
||||
* For each active connection, if RMP_TIMEOUT seconds have passed
|
||||
* since the last packet was sent, delete the connection.
|
||||
*/
|
||||
for (rtmp = RmpConns; rtmp != NULL; rtmp = rtmp->next)
|
||||
if ((rtmp->tstamp.tv_sec + RMP_TIMEOUT) < now.tv_sec) {
|
||||
syslog(LOG_WARNING, "%s: connection timed out (%u)",
|
||||
EnetStr(rtmp), rtmp->rmp.r_type);
|
||||
RemoveConn(rtmp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** FindClient -- Find client associated with a packet.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - the new packet.
|
||||
**
|
||||
** Returns:
|
||||
** Pointer to client info if found, NULL otherwise.
|
||||
**
|
||||
** Side Effects:
|
||||
** None.
|
||||
**
|
||||
** Warnings:
|
||||
** - This routine must be called with SIGHUP blocked since
|
||||
** a reconfigure can invalidate the information returned.
|
||||
*/
|
||||
|
||||
CLIENT *
|
||||
FindClient(rconn)
|
||||
register RMPCONN *rconn;
|
||||
{
|
||||
register CLIENT *ctmp;
|
||||
|
||||
for (ctmp = Clients; ctmp != NULL; ctmp = ctmp->next)
|
||||
if (bcmp((char *)&rconn->rmp.hp_hdr.saddr[0],
|
||||
(char *)&ctmp->addr[0], RMP_ADDRLEN) == 0)
|
||||
break;
|
||||
|
||||
return(ctmp);
|
||||
}
|
||||
|
||||
/*
|
||||
** Exit -- Log an error message and exit.
|
||||
**
|
||||
** Parameters:
|
||||
** sig - caught signal (or zero if not dying on a signal).
|
||||
**
|
||||
** Returns:
|
||||
** Does not return.
|
||||
**
|
||||
** Side Effects:
|
||||
** - This process ceases to exist.
|
||||
*/
|
||||
void
|
||||
Exit(sig)
|
||||
int sig;
|
||||
{
|
||||
if (sig > 0)
|
||||
syslog(LOG_ERR, "going down on signal %d", sig);
|
||||
else
|
||||
syslog(LOG_ERR, "going down with fatal error");
|
||||
BpfClose();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
** ReConfig -- Get new list of boot files and reread config files.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - All active connections are dropped.
|
||||
** - List of boot-able files is changed.
|
||||
** - List of clients is changed.
|
||||
**
|
||||
** Warnings:
|
||||
** - This routine must be called with SIGHUP blocked.
|
||||
*/
|
||||
void
|
||||
ReConfig(signo)
|
||||
int signo;
|
||||
{
|
||||
syslog(LOG_NOTICE, "reconfiguring boot server");
|
||||
|
||||
FreeConns();
|
||||
|
||||
if (GetBootFiles() == 0)
|
||||
Exit(0);
|
||||
|
||||
if (ParseConfig() == 0)
|
||||
Exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
** DebugOff -- Turn off debugging.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - Debug file is closed.
|
||||
*/
|
||||
void
|
||||
DebugOff(signo)
|
||||
int signo;
|
||||
{
|
||||
if (DbgFp != NULL)
|
||||
(void) fclose(DbgFp);
|
||||
|
||||
DbgFp = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
** DebugOn -- Turn on debugging.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - Debug file is opened/truncated if not already opened,
|
||||
** otherwise do nothing.
|
||||
*/
|
||||
void
|
||||
DebugOn(signo)
|
||||
int signo;
|
||||
{
|
||||
if (DbgFp == NULL) {
|
||||
if ((DbgFp = fopen(DbgFile, "w")) == NULL)
|
||||
syslog(LOG_ERR, "can't open debug file (%s)", DbgFile);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)rmp.h 8.1 (Berkeley) 6/4/93
|
||||
*
|
||||
* Utah $Hdr: rmp.h 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
/*
|
||||
* Define MIN/MAX sizes of RMP (ethernet) packet.
|
||||
* For ease of computation, the 4 octet CRC field is not included.
|
||||
*
|
||||
* MCLBYTES is for bpfwrite(); it is adamant about using a cluster.
|
||||
*/
|
||||
|
||||
#define RMP_MAX_PACKET MIN(1514,MCLBYTES)
|
||||
#define RMP_MIN_PACKET 60
|
||||
|
||||
/*
|
||||
* Define RMP/Ethernet Multicast address (9:0:9:0:0:4) and its length.
|
||||
*/
|
||||
#define RMP_ADDR { 0x9, 0x0, 0x9, 0x0, 0x0, 0x4 }
|
||||
#define RMP_ADDRLEN 6
|
||||
|
||||
/*
|
||||
* Define IEEE802.2 (Logical Link Control) information.
|
||||
*/
|
||||
#define IEEE_DSAP_HP 0xF8 /* Destination Service Access Point */
|
||||
#define IEEE_SSAP_HP 0xF8 /* Source Service Access Point */
|
||||
#define IEEE_CNTL_HP 0x0300 /* Type 1 / I format control information */
|
||||
|
||||
#define HPEXT_DXSAP 0x608 /* HP Destination Service Access Point */
|
||||
#define HPEXT_SXSAP 0x609 /* HP Source Service Access Point */
|
||||
|
||||
/*
|
||||
* 802.3-style "Ethernet" header.
|
||||
*/
|
||||
|
||||
struct hp_hdr {
|
||||
u_char daddr[RMP_ADDRLEN];
|
||||
u_char saddr[RMP_ADDRLEN];
|
||||
u_short len;
|
||||
};
|
||||
|
||||
/*
|
||||
* HP uses 802.2 LLC with their own local extensions. This struct makes
|
||||
* sence out of this data (encapsulated in the above 802.3 packet).
|
||||
*/
|
||||
|
||||
struct hp_llc {
|
||||
u_char dsap; /* 802.2 DSAP */
|
||||
u_char ssap; /* 802.2 SSAP */
|
||||
u_short cntrl; /* 802.2 control field */
|
||||
u_short filler; /* HP filler (must be zero) */
|
||||
u_short dxsap; /* HP extended DSAP */
|
||||
u_short sxsap; /* HP extended SSAP */
|
||||
};
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)rmp_var.h 8.1 (Berkeley) 6/4/93
|
||||
*
|
||||
* Utah $Hdr: rmp_var.h 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
/*
|
||||
* Possible values for "rmp_type" fields.
|
||||
*/
|
||||
|
||||
#define RMP_BOOT_REQ 1 /* boot request packet */
|
||||
#define RMP_BOOT_REPL 129 /* boot reply packet */
|
||||
#define RMP_READ_REQ 2 /* read request packet */
|
||||
#define RMP_READ_REPL 130 /* read reply packet */
|
||||
#define RMP_BOOT_DONE 3 /* boot complete packet */
|
||||
|
||||
/*
|
||||
* Useful constants.
|
||||
*/
|
||||
|
||||
#define RMP_VERSION 2 /* protocol version */
|
||||
#define RMP_TIMEOUT 600 /* timeout connection after ten minutes */
|
||||
#define RMP_PROBESID 0xffff /* session ID for probes */
|
||||
#define RMP_HOSTLEN 13 /* max length of server's name */
|
||||
#define RMP_MACHLEN 20 /* length of machine type field */
|
||||
|
||||
/*
|
||||
* RMP error codes
|
||||
*/
|
||||
|
||||
#define RMP_E_OKAY 0
|
||||
#define RMP_E_EOF 2 /* read reply: returned end of file */
|
||||
#define RMP_E_ABORT 3 /* abort operation */
|
||||
#define RMP_E_BUSY 4 /* boot reply: server busy */
|
||||
#define RMP_E_TIMEOUT 5 /* lengthen time out (not implemented) */
|
||||
#define RMP_E_NOFILE 16 /* boot reply: file does not exist */
|
||||
#define RMP_E_OPENFILE 17 /* boot reply: file open failed */
|
||||
#define RMP_E_NODFLT 18 /* boot reply: default file does not exist */
|
||||
#define RMP_E_OPENDFLT 19 /* boot reply: default file open failed */
|
||||
#define RMP_E_BADSID 25 /* read reply: bad session ID */
|
||||
#define RMP_E_BADPACKET 27 /* Bad packet detected */
|
||||
|
||||
/*
|
||||
* RMPDATALEN is the maximum number of data octets that can be stuffed
|
||||
* into an RMP packet. This excludes the 802.2 LLC w/HP extensions.
|
||||
*/
|
||||
#define RMPDATALEN (RMP_MAX_PACKET - (sizeof(struct hp_hdr) + \
|
||||
sizeof(struct hp_llc)))
|
||||
|
||||
/*
|
||||
* Define sizes of packets we send. Boot and Read replies are variable
|
||||
* in length depending on the length of `s'.
|
||||
*
|
||||
* Also, define how much space `restofpkt' can take up for outgoing
|
||||
* Boot and Read replies. Boot Request packets are effectively
|
||||
* limited to 255 bytes due to the preceding 1-byte length field.
|
||||
*/
|
||||
|
||||
#define RMPBOOTSIZE(s) (sizeof(struct hp_hdr) + sizeof(struct hp_llc) + \
|
||||
sizeof(struct rmp_boot_repl) + s - sizeof(restofpkt))
|
||||
#define RMPREADSIZE(s) (sizeof(struct hp_hdr) + sizeof(struct hp_llc) + \
|
||||
sizeof(struct rmp_read_repl) + s - sizeof(restofpkt) \
|
||||
- sizeof(u_char))
|
||||
#define RMPDONESIZE (sizeof(struct hp_hdr) + sizeof(struct hp_llc) + \
|
||||
sizeof(struct rmp_boot_done))
|
||||
#define RMPBOOTDATA 255
|
||||
#define RMPREADDATA (RMPDATALEN - \
|
||||
(2*sizeof(u_char)+sizeof(u_short)+sizeof(u_word)))
|
||||
|
||||
/*
|
||||
* This protocol defines some field sizes as "rest of ethernet packet".
|
||||
* There is no easy way to specify this in C, so we use a one character
|
||||
* field to denote it, and index past it to the end of the packet.
|
||||
*/
|
||||
|
||||
typedef char restofpkt;
|
||||
|
||||
/*
|
||||
* Due to the RMP packet layout, we'll run into alignment problems
|
||||
* on machines that cant access words on half-word boundaries. If
|
||||
* you know that your machine does not suffer from this problem,
|
||||
* add it to the hp300 #define below.
|
||||
*
|
||||
* The following macros are used to deal with this problem:
|
||||
* WORDZE(w) Return True if u_word `w' is zero, False otherwise.
|
||||
* ZEROWORD(w) Set u_word `w' to zero.
|
||||
* COPYWORD(w1,w2) Copy u_word `w1' to `w2'.
|
||||
* GETWORD(w,i) Copy u_word `w' into int `i'.
|
||||
* PUTWORD(i,w) Copy int `i' into u_word `w'.
|
||||
*
|
||||
* N.B. We do not support little endian alignment-challenged machines.
|
||||
*/
|
||||
#if defined(vax) || defined(tahoe) || defined(hp300)
|
||||
|
||||
typedef u_int u_word;
|
||||
|
||||
#define WORDZE(w) ((w) == 0)
|
||||
#define ZEROWORD(w) (w) = 0
|
||||
#define COPYWORD(w1,w2) (w2) = (w1)
|
||||
#define GETWORD(w, i) (i) = (w)
|
||||
#define PUTWORD(i, w) (w) = (i)
|
||||
|
||||
#else
|
||||
|
||||
#define _WORD_HIGHPART 0 /* XXX: assume Big Endian for now */
|
||||
#define _WORD_LOWPART 1
|
||||
|
||||
typedef struct _uword { u_short val[2]; } u_word;
|
||||
|
||||
#define WORDZE(w) \
|
||||
((w.val[_WORD_HIGHPART] == 0) && (w.val[_WORD_LOWPART] == 0))
|
||||
#define ZEROWORD(w) \
|
||||
(w).val[_WORD_HIGHPART] = (w).val[_WORD_LOWPART] = 0
|
||||
#define COPYWORD(w1, w2) \
|
||||
{ (w2).val[_WORD_HIGHPART] = (w1).val[_WORD_HIGHPART]; \
|
||||
(w2).val[_WORD_LOWPART] = (w1).val[_WORD_LOWPART]; \
|
||||
}
|
||||
#define GETWORD(w, i) \
|
||||
(i) = (((u_int)(w).val[_WORD_HIGHPART]) << 16) | (w).val[_WORD_LOWPART]
|
||||
#define PUTWORD(i, w) \
|
||||
{ (w).val[_WORD_HIGHPART] = (u_short) (((i) >> 16) & 0xffff); \
|
||||
(w).val[_WORD_LOWPART] = (u_short) (i & 0xffff); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Packet structures.
|
||||
*/
|
||||
|
||||
struct rmp_raw { /* generic RMP packet */
|
||||
u_char rmp_type; /* packet type */
|
||||
u_char rmp_rawdata[RMPDATALEN-1];
|
||||
};
|
||||
|
||||
struct rmp_boot_req { /* boot request */
|
||||
u_char rmp_type; /* packet type (RMP_BOOT_REQ) */
|
||||
u_char rmp_retcode; /* return code (0) */
|
||||
u_word rmp_seqno; /* sequence number (real time clock) */
|
||||
u_short rmp_session; /* session id (normally 0) */
|
||||
u_short rmp_version; /* protocol version (RMP_VERSION) */
|
||||
char rmp_machtype[RMP_MACHLEN]; /* machine type */
|
||||
u_char rmp_flnmsize; /* length of rmp_flnm */
|
||||
restofpkt rmp_flnm; /* name of file to be read */
|
||||
};
|
||||
|
||||
struct rmp_boot_repl { /* boot reply */
|
||||
u_char rmp_type; /* packet type (RMP_BOOT_REPL) */
|
||||
u_char rmp_retcode; /* return code (normally 0) */
|
||||
u_word rmp_seqno; /* sequence number (from boot req) */
|
||||
u_short rmp_session; /* session id (generated) */
|
||||
u_short rmp_version; /* protocol version (RMP_VERSION) */
|
||||
u_char rmp_flnmsize; /* length of rmp_flnm */
|
||||
restofpkt rmp_flnm; /* name of file (from boot req) */
|
||||
};
|
||||
|
||||
struct rmp_read_req { /* read request */
|
||||
u_char rmp_type; /* packet type (RMP_READ_REQ) */
|
||||
u_char rmp_retcode; /* return code (0) */
|
||||
u_word rmp_offset; /* file relative byte offset */
|
||||
u_short rmp_session; /* session id (from boot repl) */
|
||||
u_short rmp_size; /* max no of bytes to send */
|
||||
};
|
||||
|
||||
struct rmp_read_repl { /* read reply */
|
||||
u_char rmp_type; /* packet type (RMP_READ_REPL) */
|
||||
u_char rmp_retcode; /* return code (normally 0) */
|
||||
u_word rmp_offset; /* byte offset (from read req) */
|
||||
u_short rmp_session; /* session id (from read req) */
|
||||
restofpkt rmp_data; /* data (max size from read req) */
|
||||
u_char rmp_unused; /* padding to 16-bit boundary */
|
||||
};
|
||||
|
||||
struct rmp_boot_done { /* boot complete */
|
||||
u_char rmp_type; /* packet type (RMP_BOOT_DONE) */
|
||||
u_char rmp_retcode; /* return code (0) */
|
||||
u_word rmp_unused; /* not used (0) */
|
||||
u_short rmp_session; /* session id (from read repl) */
|
||||
};
|
||||
|
||||
struct rmp_packet {
|
||||
struct hp_hdr hp_hdr;
|
||||
struct hp_llc hp_llc;
|
||||
union {
|
||||
struct rmp_boot_req rmp_brq; /* boot request */
|
||||
struct rmp_boot_repl rmp_brpl; /* boot reply */
|
||||
struct rmp_read_req rmp_rrq; /* read request */
|
||||
struct rmp_read_repl rmp_rrpl; /* read reply */
|
||||
struct rmp_boot_done rmp_done; /* boot complete */
|
||||
struct rmp_raw rmp_raw; /* raw data */
|
||||
} rmp_proto;
|
||||
};
|
||||
|
||||
/*
|
||||
* Make life easier...
|
||||
*/
|
||||
|
||||
#define r_type rmp_proto.rmp_raw.rmp_type
|
||||
#define r_data rmp_proto.rmp_raw.rmp_data
|
||||
#define r_brq rmp_proto.rmp_brq
|
||||
#define r_brpl rmp_proto.rmp_brpl
|
||||
#define r_rrq rmp_proto.rmp_rrq
|
||||
#define r_rrpl rmp_proto.rmp_rrpl
|
||||
#define r_done rmp_proto.rmp_done
|
|
@ -0,0 +1,593 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)rmpproto.c 8.1 (Berkeley) 6/4/93
|
||||
*
|
||||
* Utah $Hdr: rmpproto.c 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)rmpproto.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include "defs.h"
|
||||
|
||||
/*
|
||||
** ProcessPacket -- determine packet type and do what's required.
|
||||
**
|
||||
** An RMP BOOT packet has been received. Look at the type field
|
||||
** and process Boot Requests, Read Requests, and Boot Complete
|
||||
** packets. Any other type will be dropped with a warning msg.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - the new connection
|
||||
** client - list of files available to this host
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - If this is a valid boot request, it will be added to
|
||||
** the linked list of outstanding requests (RmpConns).
|
||||
** - If this is a valid boot complete, its associated
|
||||
** entry in RmpConns will be deleted.
|
||||
** - Also, unless we run out of memory, a reply will be
|
||||
** sent to the host that sent the packet.
|
||||
*/
|
||||
void
|
||||
ProcessPacket(rconn, client)
|
||||
RMPCONN *rconn;
|
||||
CLIENT *client;
|
||||
{
|
||||
struct rmp_packet *rmp;
|
||||
RMPCONN *rconnout;
|
||||
|
||||
rmp = &rconn->rmp; /* cache pointer to RMP packet */
|
||||
|
||||
switch(rmp->r_type) { /* do what we came here to do */
|
||||
case RMP_BOOT_REQ: /* boot request */
|
||||
if ((rconnout = NewConn(rconn)) == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If the Session ID is 0xffff, this is a "probe"
|
||||
* packet and we do not want to add the connection
|
||||
* to the linked list of active connections. There
|
||||
* are two types of probe packets, if the Sequence
|
||||
* Number is 0 they want to know our host name, o/w
|
||||
* they want the name of the file associated with
|
||||
* the number spec'd by the Sequence Number.
|
||||
*
|
||||
* If this is an actual boot request, open the file
|
||||
* and send a reply. If SendBootRepl() does not
|
||||
* return 0, add the connection to the linked list
|
||||
* of active connections, otherwise delete it since
|
||||
* an error was encountered.
|
||||
*/
|
||||
if (rmp->r_brq.rmp_session == RMP_PROBESID) {
|
||||
if (WORDZE(rmp->r_brq.rmp_seqno))
|
||||
(void) SendServerID(rconnout);
|
||||
else
|
||||
(void) SendFileNo(rmp, rconnout,
|
||||
client? client->files:
|
||||
BootFiles);
|
||||
FreeConn(rconnout);
|
||||
} else {
|
||||
if (SendBootRepl(rmp, rconnout,
|
||||
client? client->files: BootFiles))
|
||||
AddConn(rconnout);
|
||||
else
|
||||
FreeConn(rconnout);
|
||||
}
|
||||
break;
|
||||
|
||||
case RMP_BOOT_REPL: /* boot reply (not valid) */
|
||||
syslog(LOG_WARNING, "%s: sent a boot reply",
|
||||
EnetStr(rconn));
|
||||
break;
|
||||
|
||||
case RMP_READ_REQ: /* read request */
|
||||
/*
|
||||
* Send a portion of the boot file.
|
||||
*/
|
||||
(void) SendReadRepl(rconn);
|
||||
break;
|
||||
|
||||
case RMP_READ_REPL: /* read reply (not valid) */
|
||||
syslog(LOG_WARNING, "%s: sent a read reply",
|
||||
EnetStr(rconn));
|
||||
break;
|
||||
|
||||
case RMP_BOOT_DONE: /* boot complete */
|
||||
/*
|
||||
* Remove the entry from the linked list of active
|
||||
* connections.
|
||||
*/
|
||||
(void) BootDone(rconn);
|
||||
break;
|
||||
|
||||
default: /* unknown RMP packet type */
|
||||
syslog(LOG_WARNING, "%s: unknown packet type (%u)",
|
||||
EnetStr(rconn), rmp->r_type);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** SendServerID -- send our host name to who ever requested it.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - the reply packet to be formatted.
|
||||
**
|
||||
** Returns:
|
||||
** 1 on success, 0 on failure.
|
||||
**
|
||||
** Side Effects:
|
||||
** none.
|
||||
*/
|
||||
int
|
||||
SendServerID(rconn)
|
||||
RMPCONN *rconn;
|
||||
{
|
||||
register struct rmp_packet *rpl;
|
||||
register char *src, *dst;
|
||||
register u_char *size;
|
||||
|
||||
rpl = &rconn->rmp; /* cache ptr to RMP packet */
|
||||
|
||||
/*
|
||||
* Set up assorted fields in reply packet.
|
||||
*/
|
||||
rpl->r_brpl.rmp_type = RMP_BOOT_REPL;
|
||||
rpl->r_brpl.rmp_retcode = RMP_E_OKAY;
|
||||
ZEROWORD(rpl->r_brpl.rmp_seqno);
|
||||
rpl->r_brpl.rmp_session = 0;
|
||||
rpl->r_brpl.rmp_version = RMP_VERSION;
|
||||
|
||||
size = &rpl->r_brpl.rmp_flnmsize; /* ptr to length of host name */
|
||||
|
||||
/*
|
||||
* Copy our host name into the reply packet incrementing the
|
||||
* length as we go. Stop at RMP_HOSTLEN or the first dot.
|
||||
*/
|
||||
src = MyHost;
|
||||
dst = (char *) &rpl->r_brpl.rmp_flnm;
|
||||
for (*size = 0; *size < RMP_HOSTLEN; (*size)++) {
|
||||
if (*src == '.' || *src == '\0')
|
||||
break;
|
||||
*dst++ = *src++;
|
||||
}
|
||||
|
||||
rconn->rmplen = RMPBOOTSIZE(*size); /* set packet length */
|
||||
|
||||
return(SendPacket(rconn)); /* send packet */
|
||||
}
|
||||
|
||||
/*
|
||||
** SendFileNo -- send the name of a bootable file to the requester.
|
||||
**
|
||||
** Parameters:
|
||||
** req - RMP BOOT packet containing the request.
|
||||
** rconn - the reply packet to be formatted.
|
||||
** filelist - list of files available to the requester.
|
||||
**
|
||||
** Returns:
|
||||
** 1 on success, 0 on failure.
|
||||
**
|
||||
** Side Effects:
|
||||
** none.
|
||||
*/
|
||||
int
|
||||
SendFileNo(req, rconn, filelist)
|
||||
struct rmp_packet *req;
|
||||
RMPCONN *rconn;
|
||||
char *filelist[];
|
||||
{
|
||||
register struct rmp_packet *rpl;
|
||||
register char *src, *dst;
|
||||
register u_char *size, i;
|
||||
|
||||
GETWORD(req->r_brpl.rmp_seqno, i); /* SeqNo is really FileNo */
|
||||
rpl = &rconn->rmp; /* cache ptr to RMP packet */
|
||||
|
||||
/*
|
||||
* Set up assorted fields in reply packet.
|
||||
*/
|
||||
rpl->r_brpl.rmp_type = RMP_BOOT_REPL;
|
||||
PUTWORD(i, rpl->r_brpl.rmp_seqno);
|
||||
i--;
|
||||
rpl->r_brpl.rmp_session = 0;
|
||||
rpl->r_brpl.rmp_version = RMP_VERSION;
|
||||
|
||||
size = &rpl->r_brpl.rmp_flnmsize; /* ptr to length of filename */
|
||||
*size = 0; /* init length to zero */
|
||||
|
||||
/*
|
||||
* Copy the file name into the reply packet incrementing the
|
||||
* length as we go. Stop at end of string or when RMPBOOTDATA
|
||||
* characters have been copied. Also, set return code to
|
||||
* indicate success or "no more files".
|
||||
*/
|
||||
if (i < C_MAXFILE && filelist[i] != NULL) {
|
||||
src = filelist[i];
|
||||
dst = (char *)&rpl->r_brpl.rmp_flnm;
|
||||
for (; *src && *size < RMPBOOTDATA; (*size)++) {
|
||||
if (*src == '\0')
|
||||
break;
|
||||
*dst++ = *src++;
|
||||
}
|
||||
rpl->r_brpl.rmp_retcode = RMP_E_OKAY;
|
||||
} else
|
||||
rpl->r_brpl.rmp_retcode = RMP_E_NODFLT;
|
||||
|
||||
rconn->rmplen = RMPBOOTSIZE(*size); /* set packet length */
|
||||
|
||||
return(SendPacket(rconn)); /* send packet */
|
||||
}
|
||||
|
||||
/*
|
||||
** SendBootRepl -- open boot file and respond to boot request.
|
||||
**
|
||||
** Parameters:
|
||||
** req - RMP BOOT packet containing the request.
|
||||
** rconn - the reply packet to be formatted.
|
||||
** filelist - list of files available to the requester.
|
||||
**
|
||||
** Returns:
|
||||
** 1 on success, 0 on failure.
|
||||
**
|
||||
** Side Effects:
|
||||
** none.
|
||||
*/
|
||||
int
|
||||
SendBootRepl(req, rconn, filelist)
|
||||
struct rmp_packet *req;
|
||||
RMPCONN *rconn;
|
||||
char *filelist[];
|
||||
{
|
||||
int retval;
|
||||
char *filename, filepath[RMPBOOTDATA+1];
|
||||
RMPCONN *oldconn;
|
||||
register struct rmp_packet *rpl;
|
||||
register char *src, *dst1, *dst2;
|
||||
register u_char i;
|
||||
|
||||
/*
|
||||
* If another connection already exists, delete it since we
|
||||
* are obviously starting again.
|
||||
*/
|
||||
if ((oldconn = FindConn(rconn)) != NULL) {
|
||||
syslog(LOG_WARNING, "%s: dropping existing connection",
|
||||
EnetStr(oldconn));
|
||||
RemoveConn(oldconn);
|
||||
}
|
||||
|
||||
rpl = &rconn->rmp; /* cache ptr to RMP packet */
|
||||
|
||||
/*
|
||||
* Set up assorted fields in reply packet.
|
||||
*/
|
||||
rpl->r_brpl.rmp_type = RMP_BOOT_REPL;
|
||||
COPYWORD(req->r_brq.rmp_seqno, rpl->r_brpl.rmp_seqno);
|
||||
rpl->r_brpl.rmp_session = GenSessID();
|
||||
rpl->r_brpl.rmp_version = RMP_VERSION;
|
||||
rpl->r_brpl.rmp_flnmsize = req->r_brq.rmp_flnmsize;
|
||||
|
||||
/*
|
||||
* Copy file name to `filepath' string, and into reply packet.
|
||||
*/
|
||||
src = &req->r_brq.rmp_flnm;
|
||||
dst1 = filepath;
|
||||
dst2 = &rpl->r_brpl.rmp_flnm;
|
||||
for (i = 0; i < req->r_brq.rmp_flnmsize; i++)
|
||||
*dst1++ = *dst2++ = *src++;
|
||||
*dst1 = '\0';
|
||||
|
||||
/*
|
||||
* If we are booting HP-UX machines, their secondary loader will
|
||||
* ask for files like "/hp-ux". As a security measure, we do not
|
||||
* allow boot files to lay outside the boot directory (unless they
|
||||
* are purposely link'd out. So, make `filename' become the path-
|
||||
* stripped file name and spoof the client into thinking that it
|
||||
* really got what it wanted.
|
||||
*/
|
||||
filename = (filename = rindex(filepath,'/'))? ++filename: filepath;
|
||||
|
||||
/*
|
||||
* Check that this is a valid boot file name.
|
||||
*/
|
||||
for (i = 0; i < C_MAXFILE && filelist[i] != NULL; i++)
|
||||
if (STREQN(filename, filelist[i]))
|
||||
goto match;
|
||||
|
||||
/*
|
||||
* Invalid boot file name, set error and send reply packet.
|
||||
*/
|
||||
rpl->r_brpl.rmp_retcode = RMP_E_NOFILE;
|
||||
retval = 0;
|
||||
goto sendpkt;
|
||||
|
||||
match:
|
||||
/*
|
||||
* This is a valid boot file. Open the file and save the file
|
||||
* descriptor associated with this connection and set success
|
||||
* indication. If the file couldnt be opened, set error:
|
||||
* "no such file or dir" - RMP_E_NOFILE
|
||||
* "file table overflow" - RMP_E_BUSY
|
||||
* "too many open files" - RMP_E_BUSY
|
||||
* anything else - RMP_E_OPENFILE
|
||||
*/
|
||||
if ((rconn->bootfd = open(filename, O_RDONLY, 0600)) < 0) {
|
||||
rpl->r_brpl.rmp_retcode = (errno == ENOENT)? RMP_E_NOFILE:
|
||||
(errno == EMFILE || errno == ENFILE)? RMP_E_BUSY:
|
||||
RMP_E_OPENFILE;
|
||||
retval = 0;
|
||||
} else {
|
||||
rpl->r_brpl.rmp_retcode = RMP_E_OKAY;
|
||||
retval = 1;
|
||||
}
|
||||
|
||||
sendpkt:
|
||||
syslog(LOG_INFO, "%s: request to boot %s (%s)",
|
||||
EnetStr(rconn), filename, retval? "granted": "denied");
|
||||
|
||||
rconn->rmplen = RMPBOOTSIZE(rpl->r_brpl.rmp_flnmsize);
|
||||
|
||||
return (retval & SendPacket(rconn));
|
||||
}
|
||||
|
||||
/*
|
||||
** SendReadRepl -- send a portion of the boot file to the requester.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - the reply packet to be formatted.
|
||||
**
|
||||
** Returns:
|
||||
** 1 on success, 0 on failure.
|
||||
**
|
||||
** Side Effects:
|
||||
** none.
|
||||
*/
|
||||
int
|
||||
SendReadRepl(rconn)
|
||||
RMPCONN *rconn;
|
||||
{
|
||||
int retval;
|
||||
RMPCONN *oldconn;
|
||||
register struct rmp_packet *rpl, *req;
|
||||
register int size = 0;
|
||||
int madeconn = 0;
|
||||
|
||||
/*
|
||||
* Find the old connection. If one doesnt exist, create one only
|
||||
* to return the error code.
|
||||
*/
|
||||
if ((oldconn = FindConn(rconn)) == NULL) {
|
||||
if ((oldconn = NewConn(rconn)) == NULL)
|
||||
return(0);
|
||||
syslog(LOG_ERR, "SendReadRepl: no active connection (%s)",
|
||||
EnetStr(rconn));
|
||||
madeconn++;
|
||||
}
|
||||
|
||||
req = &rconn->rmp; /* cache ptr to request packet */
|
||||
rpl = &oldconn->rmp; /* cache ptr to reply packet */
|
||||
|
||||
if (madeconn) { /* no active connection above; abort */
|
||||
rpl->r_rrpl.rmp_retcode = RMP_E_ABORT;
|
||||
retval = 1;
|
||||
goto sendpkt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure Session ID's match.
|
||||
*/
|
||||
if (req->r_rrq.rmp_session !=
|
||||
((rpl->r_type == RMP_BOOT_REPL)? rpl->r_brpl.rmp_session:
|
||||
rpl->r_rrpl.rmp_session)) {
|
||||
syslog(LOG_ERR, "SendReadRepl: bad session id (%s)",
|
||||
EnetStr(rconn));
|
||||
rpl->r_rrpl.rmp_retcode = RMP_E_BADSID;
|
||||
retval = 1;
|
||||
goto sendpkt;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the requester asks for more data than we can fit,
|
||||
* silently clamp the request size down to RMPREADDATA.
|
||||
*
|
||||
* N.B. I do not know if this is "legal", however it seems
|
||||
* to work. This is necessary for bpfwrite() on machines
|
||||
* with MCLBYTES less than 1514.
|
||||
*/
|
||||
if (req->r_rrq.rmp_size > RMPREADDATA)
|
||||
req->r_rrq.rmp_size = RMPREADDATA;
|
||||
|
||||
/*
|
||||
* Position read head on file according to info in request packet.
|
||||
*/
|
||||
GETWORD(req->r_rrq.rmp_offset, size);
|
||||
if (lseek(oldconn->bootfd, (off_t)size, L_SET) < 0) {
|
||||
syslog(LOG_ERR, "SendReadRepl: lseek: %m (%s)",
|
||||
EnetStr(rconn));
|
||||
rpl->r_rrpl.rmp_retcode = RMP_E_ABORT;
|
||||
retval = 1;
|
||||
goto sendpkt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read data directly into reply packet.
|
||||
*/
|
||||
if ((size = read(oldconn->bootfd, &rpl->r_rrpl.rmp_data,
|
||||
(int) req->r_rrq.rmp_size)) <= 0) {
|
||||
if (size < 0) {
|
||||
syslog(LOG_ERR, "SendReadRepl: read: %m (%s)",
|
||||
EnetStr(rconn));
|
||||
rpl->r_rrpl.rmp_retcode = RMP_E_ABORT;
|
||||
} else {
|
||||
rpl->r_rrpl.rmp_retcode = RMP_E_EOF;
|
||||
}
|
||||
retval = 1;
|
||||
goto sendpkt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set success indication.
|
||||
*/
|
||||
rpl->r_rrpl.rmp_retcode = RMP_E_OKAY;
|
||||
|
||||
sendpkt:
|
||||
/*
|
||||
* Set up assorted fields in reply packet.
|
||||
*/
|
||||
rpl->r_rrpl.rmp_type = RMP_READ_REPL;
|
||||
COPYWORD(req->r_rrq.rmp_offset, rpl->r_rrpl.rmp_offset);
|
||||
rpl->r_rrpl.rmp_session = req->r_rrq.rmp_session;
|
||||
|
||||
oldconn->rmplen = RMPREADSIZE(size); /* set size of packet */
|
||||
|
||||
retval &= SendPacket(oldconn); /* send packet */
|
||||
|
||||
if (madeconn) /* clean up after ourself */
|
||||
FreeConn(oldconn);
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/*
|
||||
** BootDone -- free up memory allocated for a connection.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - incoming boot complete packet.
|
||||
**
|
||||
** Returns:
|
||||
** 1 on success, 0 on failure.
|
||||
**
|
||||
** Side Effects:
|
||||
** none.
|
||||
*/
|
||||
int
|
||||
BootDone(rconn)
|
||||
RMPCONN *rconn;
|
||||
{
|
||||
RMPCONN *oldconn;
|
||||
struct rmp_packet *rpl;
|
||||
|
||||
/*
|
||||
* If we cant find the connection, ignore the request.
|
||||
*/
|
||||
if ((oldconn = FindConn(rconn)) == NULL) {
|
||||
syslog(LOG_ERR, "BootDone: no existing connection (%s)",
|
||||
EnetStr(rconn));
|
||||
return(0);
|
||||
}
|
||||
|
||||
rpl = &oldconn->rmp; /* cache ptr to RMP packet */
|
||||
|
||||
/*
|
||||
* Make sure Session ID's match.
|
||||
*/
|
||||
if (rconn->rmp.r_rrq.rmp_session !=
|
||||
((rpl->r_type == RMP_BOOT_REPL)? rpl->r_brpl.rmp_session:
|
||||
rpl->r_rrpl.rmp_session)) {
|
||||
syslog(LOG_ERR, "BootDone: bad session id (%s)",
|
||||
EnetStr(rconn));
|
||||
return(0);
|
||||
}
|
||||
|
||||
RemoveConn(oldconn); /* remove connection */
|
||||
|
||||
syslog(LOG_INFO, "%s: boot complete", EnetStr(rconn));
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
** SendPacket -- send an RMP packet to a remote host.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - packet to be sent.
|
||||
**
|
||||
** Returns:
|
||||
** 1 on success, 0 on failure.
|
||||
**
|
||||
** Side Effects:
|
||||
** none.
|
||||
*/
|
||||
int
|
||||
SendPacket(rconn)
|
||||
register RMPCONN *rconn;
|
||||
{
|
||||
/*
|
||||
* Set Ethernet Destination address to Source (BPF and the enet
|
||||
* driver will take care of getting our source address set).
|
||||
*/
|
||||
bcopy((char *)&rconn->rmp.hp_hdr.saddr[0],
|
||||
(char *)&rconn->rmp.hp_hdr.daddr[0], RMP_ADDRLEN);
|
||||
rconn->rmp.hp_hdr.len = rconn->rmplen - sizeof(struct hp_hdr);
|
||||
|
||||
/*
|
||||
* Reverse 802.2/HP Extended Source & Destination Access Pts.
|
||||
*/
|
||||
rconn->rmp.hp_llc.dxsap = HPEXT_SXSAP;
|
||||
rconn->rmp.hp_llc.sxsap = HPEXT_DXSAP;
|
||||
|
||||
/*
|
||||
* Last time this connection was active.
|
||||
*/
|
||||
(void) gettimeofday(&rconn->tstamp, (struct timezone *)0);
|
||||
|
||||
if (DbgFp != NULL) /* display packet */
|
||||
DispPkt(rconn,DIR_SENT);
|
||||
|
||||
/*
|
||||
* Send RMP packet to remote host.
|
||||
*/
|
||||
return(BpfWrite(rconn));
|
||||
}
|
|
@ -0,0 +1,556 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)utils.c 8.1 (Berkeley) 6/4/93
|
||||
*
|
||||
* Utah $Hdr: utils.c 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)utils.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include "defs.h"
|
||||
|
||||
/*
|
||||
** DispPkt -- Display the contents of an RMPCONN packet.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - packet to be displayed.
|
||||
** direct - direction packet is going (DIR_*).
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** None.
|
||||
*/
|
||||
void
|
||||
DispPkt(rconn, direct)
|
||||
RMPCONN *rconn;
|
||||
int direct;
|
||||
{
|
||||
static char BootFmt[] = "\t\tRetCode:%u SeqNo:%lx SessID:%x Vers:%u";
|
||||
static char ReadFmt[] = "\t\tRetCode:%u Offset:%lx SessID:%x\n";
|
||||
|
||||
struct tm *tmp;
|
||||
register struct rmp_packet *rmp;
|
||||
int i, omask;
|
||||
u_int t;
|
||||
|
||||
/*
|
||||
* Since we will be working with RmpConns as well as DbgFp, we
|
||||
* must block signals that can affect either.
|
||||
*/
|
||||
omask = sigblock(sigmask(SIGHUP)|sigmask(SIGUSR1)|sigmask(SIGUSR2));
|
||||
|
||||
if (DbgFp == NULL) { /* sanity */
|
||||
(void) sigsetmask(omask);
|
||||
return;
|
||||
}
|
||||
|
||||
/* display direction packet is going using '>>>' or '<<<' */
|
||||
fputs((direct==DIR_RCVD)?"<<< ":(direct==DIR_SENT)?">>> ":"", DbgFp);
|
||||
|
||||
/* display packet timestamp */
|
||||
tmp = localtime((time_t *)&rconn->tstamp.tv_sec);
|
||||
fprintf(DbgFp, "%02d:%02d:%02d.%06ld ", tmp->tm_hour, tmp->tm_min,
|
||||
tmp->tm_sec, rconn->tstamp.tv_usec);
|
||||
|
||||
/* display src or dst addr and information about network interface */
|
||||
fprintf(DbgFp, "Addr: %s Intf: %s\n", EnetStr(rconn), IntfName);
|
||||
|
||||
rmp = &rconn->rmp;
|
||||
|
||||
/* display IEEE 802.2 Logical Link Control header */
|
||||
(void) fprintf(DbgFp, "\t802.2 LLC: DSAP:%x SSAP:%x CTRL:%x\n",
|
||||
rmp->hp_llc.dsap, rmp->hp_llc.ssap, rmp->hp_llc.cntrl);
|
||||
|
||||
/* display HP extensions to 802.2 Logical Link Control header */
|
||||
(void) fprintf(DbgFp, "\tHP Ext: DXSAP:%x SXSAP:%x\n",
|
||||
rmp->hp_llc.dxsap, rmp->hp_llc.sxsap);
|
||||
|
||||
/*
|
||||
* Display information about RMP packet using type field to
|
||||
* determine what kind of packet this is.
|
||||
*/
|
||||
switch(rmp->r_type) {
|
||||
case RMP_BOOT_REQ: /* boot request */
|
||||
(void) fprintf(DbgFp, "\tBoot Request:");
|
||||
GETWORD(rmp->r_brq.rmp_seqno, t);
|
||||
if (rmp->r_brq.rmp_session == RMP_PROBESID) {
|
||||
if (WORDZE(rmp->r_brq.rmp_seqno))
|
||||
fputs(" (Send Server ID)", DbgFp);
|
||||
else
|
||||
fprintf(DbgFp," (Send Filename #%u)",t);
|
||||
}
|
||||
(void) fputc('\n', DbgFp);
|
||||
(void) fprintf(DbgFp, BootFmt, rmp->r_brq.rmp_retcode,
|
||||
t, rmp->r_brq.rmp_session,
|
||||
rmp->r_brq.rmp_version);
|
||||
(void) fprintf(DbgFp, "\n\t\tMachine Type: ");
|
||||
for (i = 0; i < RMP_MACHLEN; i++)
|
||||
(void) fputc(rmp->r_brq.rmp_machtype[i], DbgFp);
|
||||
DspFlnm(rmp->r_brq.rmp_flnmsize, &rmp->r_brq.rmp_flnm);
|
||||
break;
|
||||
case RMP_BOOT_REPL: /* boot reply */
|
||||
fprintf(DbgFp, "\tBoot Reply:\n");
|
||||
GETWORD(rmp->r_brpl.rmp_seqno, t);
|
||||
(void) fprintf(DbgFp, BootFmt, rmp->r_brpl.rmp_retcode,
|
||||
t, rmp->r_brpl.rmp_session,
|
||||
rmp->r_brpl.rmp_version);
|
||||
DspFlnm(rmp->r_brpl.rmp_flnmsize,&rmp->r_brpl.rmp_flnm);
|
||||
break;
|
||||
case RMP_READ_REQ: /* read request */
|
||||
(void) fprintf(DbgFp, "\tRead Request:\n");
|
||||
GETWORD(rmp->r_rrq.rmp_offset, t);
|
||||
(void) fprintf(DbgFp, ReadFmt, rmp->r_rrq.rmp_retcode,
|
||||
t, rmp->r_rrq.rmp_session);
|
||||
(void) fprintf(DbgFp, "\t\tNoOfBytes: %u\n",
|
||||
rmp->r_rrq.rmp_size);
|
||||
break;
|
||||
case RMP_READ_REPL: /* read reply */
|
||||
(void) fprintf(DbgFp, "\tRead Reply:\n");
|
||||
GETWORD(rmp->r_rrpl.rmp_offset, t);
|
||||
(void) fprintf(DbgFp, ReadFmt, rmp->r_rrpl.rmp_retcode,
|
||||
t, rmp->r_rrpl.rmp_session);
|
||||
(void) fprintf(DbgFp, "\t\tNoOfBytesSent: %d\n",
|
||||
rconn->rmplen - RMPREADSIZE(0));
|
||||
break;
|
||||
case RMP_BOOT_DONE: /* boot complete */
|
||||
(void) fprintf(DbgFp, "\tBoot Complete:\n");
|
||||
(void) fprintf(DbgFp, "\t\tRetCode:%u SessID:%x\n",
|
||||
rmp->r_done.rmp_retcode,
|
||||
rmp->r_done.rmp_session);
|
||||
break;
|
||||
default: /* ??? */
|
||||
(void) fprintf(DbgFp, "\tUnknown Type:(%d)\n",
|
||||
rmp->r_type);
|
||||
}
|
||||
(void) fputc('\n', DbgFp);
|
||||
(void) fflush(DbgFp);
|
||||
|
||||
(void) sigsetmask(omask); /* reset old signal mask */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** GetEtherAddr -- convert an RMP (Ethernet) address into a string.
|
||||
**
|
||||
** An RMP BOOT packet has been received. Look at the type field
|
||||
** and process Boot Requests, Read Requests, and Boot Complete
|
||||
** packets. Any other type will be dropped with a warning msg.
|
||||
**
|
||||
** Parameters:
|
||||
** addr - array of RMP_ADDRLEN bytes.
|
||||
**
|
||||
** Returns:
|
||||
** Pointer to static string representation of `addr'.
|
||||
**
|
||||
** Side Effects:
|
||||
** None.
|
||||
**
|
||||
** Warnings:
|
||||
** - The return value points to a static buffer; it must
|
||||
** be copied if it's to be saved.
|
||||
** - For speed, we assume a u_char consists of 8 bits.
|
||||
*/
|
||||
char *
|
||||
GetEtherAddr(addr)
|
||||
u_char *addr;
|
||||
{
|
||||
static char Hex[] = "0123456789abcdef";
|
||||
static char etherstr[RMP_ADDRLEN*3];
|
||||
register int i;
|
||||
register char *cp1, *cp2;
|
||||
|
||||
/*
|
||||
* For each byte in `addr', convert it to "<hexchar><hexchar>:".
|
||||
* The last byte does not get a trailing `:' appended.
|
||||
*/
|
||||
i = 0;
|
||||
cp1 = (char *)addr;
|
||||
cp2 = etherstr;
|
||||
for(;;) {
|
||||
*cp2++ = Hex[*cp1 >> 4 & 0xf];
|
||||
*cp2++ = Hex[*cp1++ & 0xf];
|
||||
if (++i == RMP_ADDRLEN)
|
||||
break;
|
||||
*cp2++ = ':';
|
||||
}
|
||||
*cp2 = '\0';
|
||||
|
||||
return(etherstr);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** DispFlnm -- Print a string of bytes to DbgFp (often, a file name).
|
||||
**
|
||||
** Parameters:
|
||||
** size - number of bytes to print.
|
||||
** flnm - address of first byte.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - Characters are sent to `DbgFp'.
|
||||
*/
|
||||
void
|
||||
DspFlnm(size, flnm)
|
||||
register u_int size;
|
||||
register char *flnm;
|
||||
{
|
||||
register int i;
|
||||
|
||||
(void) fprintf(DbgFp, "\n\t\tFile Name (%d): <", size);
|
||||
for (i = 0; i < size; i++)
|
||||
(void) fputc(*flnm++, DbgFp);
|
||||
(void) fputs(">\n", DbgFp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** NewClient -- allocate memory for a new CLIENT.
|
||||
**
|
||||
** Parameters:
|
||||
** addr - RMP (Ethernet) address of new client.
|
||||
**
|
||||
** Returns:
|
||||
** Ptr to new CLIENT or NULL if we ran out of memory.
|
||||
**
|
||||
** Side Effects:
|
||||
** - Memory will be malloc'd for the new CLIENT.
|
||||
** - If malloc() fails, a log message will be generated.
|
||||
*/
|
||||
CLIENT *
|
||||
NewClient(addr)
|
||||
u_char *addr;
|
||||
{
|
||||
CLIENT *ctmp;
|
||||
|
||||
if ((ctmp = (CLIENT *) malloc(sizeof(CLIENT))) == NULL) {
|
||||
syslog(LOG_ERR, "NewClient: out of memory (%s)",
|
||||
GetEtherAddr(addr));
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
bzero(ctmp, sizeof(CLIENT));
|
||||
bcopy(addr, &ctmp->addr[0], RMP_ADDRLEN);
|
||||
return(ctmp);
|
||||
}
|
||||
|
||||
/*
|
||||
** FreeClient -- free linked list of Clients.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - All malloc'd memory associated with the linked list of
|
||||
** CLIENTS will be free'd; `Clients' will be set to NULL.
|
||||
**
|
||||
** Warnings:
|
||||
** - This routine must be called with SIGHUP blocked.
|
||||
*/
|
||||
void
|
||||
FreeClients()
|
||||
{
|
||||
register CLIENT *ctmp;
|
||||
|
||||
while (Clients != NULL) {
|
||||
ctmp = Clients;
|
||||
Clients = Clients->next;
|
||||
FreeClient(ctmp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** NewStr -- allocate memory for a character array.
|
||||
**
|
||||
** Parameters:
|
||||
** str - null terminated character array.
|
||||
**
|
||||
** Returns:
|
||||
** Ptr to new character array or NULL if we ran out of memory.
|
||||
**
|
||||
** Side Effects:
|
||||
** - Memory will be malloc'd for the new character array.
|
||||
** - If malloc() fails, a log message will be generated.
|
||||
*/
|
||||
char *
|
||||
NewStr(str)
|
||||
char *str;
|
||||
{
|
||||
char *stmp;
|
||||
|
||||
if ((stmp = (char *)malloc((unsigned) (strlen(str)+1))) == NULL) {
|
||||
syslog(LOG_ERR, "NewStr: out of memory (%s)", str);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
(void) strcpy(stmp, str);
|
||||
return(stmp);
|
||||
}
|
||||
|
||||
/*
|
||||
** To save time, NewConn and FreeConn maintain a cache of one RMPCONN
|
||||
** in `LastFree' (defined below).
|
||||
*/
|
||||
|
||||
static RMPCONN *LastFree = NULL;
|
||||
|
||||
/*
|
||||
** NewConn -- allocate memory for a new RMPCONN connection.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - initialization template for new connection.
|
||||
**
|
||||
** Returns:
|
||||
** Ptr to new RMPCONN or NULL if we ran out of memory.
|
||||
**
|
||||
** Side Effects:
|
||||
** - Memory may be malloc'd for the new RMPCONN (if not cached).
|
||||
** - If malloc() fails, a log message will be generated.
|
||||
*/
|
||||
RMPCONN *
|
||||
NewConn(rconn)
|
||||
RMPCONN *rconn;
|
||||
{
|
||||
RMPCONN *rtmp;
|
||||
|
||||
if (LastFree == NULL) { /* nothing cached; make a new one */
|
||||
if ((rtmp = (RMPCONN *) malloc(sizeof(RMPCONN))) == NULL) {
|
||||
syslog(LOG_ERR, "NewConn: out of memory (%s)",
|
||||
EnetStr(rconn));
|
||||
return(NULL);
|
||||
}
|
||||
} else { /* use the cached RMPCONN */
|
||||
rtmp = LastFree;
|
||||
LastFree = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy template into `rtmp', init file descriptor to `-1' and
|
||||
* set ptr to next elem NULL.
|
||||
*/
|
||||
bcopy((char *)rconn, (char *)rtmp, sizeof(RMPCONN));
|
||||
rtmp->bootfd = -1;
|
||||
rtmp->next = NULL;
|
||||
|
||||
return(rtmp);
|
||||
}
|
||||
|
||||
/*
|
||||
** FreeConn -- Free memory associated with an RMPCONN connection.
|
||||
**
|
||||
** Parameters:
|
||||
** rtmp - ptr to RMPCONN to be free'd.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - Memory associated with `rtmp' may be free'd (or cached).
|
||||
** - File desc associated with `rtmp->bootfd' will be closed.
|
||||
*/
|
||||
void
|
||||
FreeConn(rtmp)
|
||||
register RMPCONN *rtmp;
|
||||
{
|
||||
/*
|
||||
* If the file descriptor is in use, close the file.
|
||||
*/
|
||||
if (rtmp->bootfd >= 0) {
|
||||
(void) close(rtmp->bootfd);
|
||||
rtmp->bootfd = -1;
|
||||
}
|
||||
|
||||
if (LastFree == NULL) /* cache for next time */
|
||||
rtmp = LastFree;
|
||||
else /* already one cached; free this one */
|
||||
free((char *)rtmp);
|
||||
}
|
||||
|
||||
/*
|
||||
** FreeConns -- free linked list of RMPCONN connections.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - All malloc'd memory associated with the linked list of
|
||||
** connections will be free'd; `RmpConns' will be set to NULL.
|
||||
** - If LastFree is != NULL, it too will be free'd & NULL'd.
|
||||
**
|
||||
** Warnings:
|
||||
** - This routine must be called with SIGHUP blocked.
|
||||
*/
|
||||
void
|
||||
FreeConns()
|
||||
{
|
||||
register RMPCONN *rtmp;
|
||||
|
||||
while (RmpConns != NULL) {
|
||||
rtmp = RmpConns;
|
||||
RmpConns = RmpConns->next;
|
||||
FreeConn(rtmp);
|
||||
}
|
||||
|
||||
if (LastFree != NULL) {
|
||||
free((char *)LastFree);
|
||||
LastFree = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** AddConn -- Add a connection to the linked list of connections.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - connection to be added.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - RmpConn will point to new connection.
|
||||
**
|
||||
** Warnings:
|
||||
** - This routine must be called with SIGHUP blocked.
|
||||
*/
|
||||
void
|
||||
AddConn(rconn)
|
||||
register RMPCONN *rconn;
|
||||
{
|
||||
if (RmpConns != NULL)
|
||||
rconn->next = RmpConns;
|
||||
RmpConns = rconn;
|
||||
}
|
||||
|
||||
/*
|
||||
** FindConn -- Find a connection in the linked list of connections.
|
||||
**
|
||||
** We use the RMP (Ethernet) address as the basis for determining
|
||||
** if this is the same connection. According to the Remote Maint
|
||||
** Protocol, we can only have one connection with any machine.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - connection to be found.
|
||||
**
|
||||
** Returns:
|
||||
** Matching connection from linked list or NULL if not found.
|
||||
**
|
||||
** Side Effects:
|
||||
** None.
|
||||
**
|
||||
** Warnings:
|
||||
** - This routine must be called with SIGHUP blocked.
|
||||
*/
|
||||
RMPCONN *
|
||||
FindConn(rconn)
|
||||
register RMPCONN *rconn;
|
||||
{
|
||||
register RMPCONN *rtmp;
|
||||
|
||||
for (rtmp = RmpConns; rtmp != NULL; rtmp = rtmp->next)
|
||||
if (bcmp((char *)&rconn->rmp.hp_hdr.saddr[0],
|
||||
(char *)&rtmp->rmp.hp_hdr.saddr[0], RMP_ADDRLEN) == 0)
|
||||
break;
|
||||
|
||||
return(rtmp);
|
||||
}
|
||||
|
||||
/*
|
||||
** RemoveConn -- Remove a connection from the linked list of connections.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - connection to be removed.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - If found, an RMPCONN will cease to exist and it will
|
||||
** be removed from the linked list.
|
||||
**
|
||||
** Warnings:
|
||||
** - This routine must be called with SIGHUP blocked.
|
||||
*/
|
||||
void
|
||||
RemoveConn(rconn)
|
||||
register RMPCONN *rconn;
|
||||
{
|
||||
register RMPCONN *thisrconn, *lastrconn;
|
||||
|
||||
if (RmpConns == rconn) { /* easy case */
|
||||
RmpConns = RmpConns->next;
|
||||
FreeConn(rconn);
|
||||
} else { /* must traverse linked list */
|
||||
lastrconn = RmpConns; /* set back ptr */
|
||||
thisrconn = lastrconn->next; /* set current ptr */
|
||||
while (thisrconn != NULL) {
|
||||
if (rconn == thisrconn) { /* found it */
|
||||
lastrconn->next = thisrconn->next;
|
||||
FreeConn(thisrconn);
|
||||
break;
|
||||
}
|
||||
lastrconn = thisrconn;
|
||||
thisrconn = thisrconn->next;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue