utils.c revision 27079
11592Srgrimes/*
21592Srgrimes * Copyright (c) 1988, 1992 The University of Utah and the Center
31592Srgrimes *	for Software Science (CSS).
41592Srgrimes * Copyright (c) 1992, 1993
51592Srgrimes *	The Regents of the University of California.  All rights reserved.
61592Srgrimes *
71592Srgrimes * This code is derived from software contributed to Berkeley by
81592Srgrimes * the Center for Software Science of the University of Utah Computer
91592Srgrimes * Science Department.  CSS requests users of this software to return
101592Srgrimes * to css-dist@cs.utah.edu any improvements that they make and grant
111592Srgrimes * CSS redistribution rights.
121592Srgrimes *
131592Srgrimes * Redistribution and use in source and binary forms, with or without
141592Srgrimes * modification, are permitted provided that the following conditions
151592Srgrimes * are met:
161592Srgrimes * 1. Redistributions of source code must retain the above copyright
171592Srgrimes *    notice, this list of conditions and the following disclaimer.
181592Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
191592Srgrimes *    notice, this list of conditions and the following disclaimer in the
201592Srgrimes *    documentation and/or other materials provided with the distribution.
211592Srgrimes * 3. All advertising materials mentioning features or use of this software
221592Srgrimes *    must display the following acknowledgement:
231592Srgrimes *	This product includes software developed by the University of
241592Srgrimes *	California, Berkeley and its contributors.
251592Srgrimes * 4. Neither the name of the University nor the names of its contributors
261592Srgrimes *    may be used to endorse or promote products derived from this software
271592Srgrimes *    without specific prior written permission.
281592Srgrimes *
291592Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
301592Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
311592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
321592Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
331592Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
341592Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
351592Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
361592Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
371592Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
381592Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
391592Srgrimes * SUCH DAMAGE.
401592Srgrimes *
4127074Ssteve *	from: @(#)utils.c	8.1 (Berkeley) 6/4/93
4227079Ssteve *	$Id: utils.c,v 1.2 1997/06/29 19:00:29 steve Exp $
431592Srgrimes *
4427074Ssteve * From: Utah Hdr: utils.c 3.1 92/07/06
451592Srgrimes * Author: Jeff Forys, University of Utah CSS
461592Srgrimes */
471592Srgrimes
481592Srgrimes#ifndef lint
4927077Sstevestatic const char sccsid[] = "@(#)utils.c	8.1 (Berkeley) 6/4/93";
501592Srgrimes#endif /* not lint */
511592Srgrimes
521592Srgrimes#include <sys/param.h>
5327077Ssteve#include <sys/time.h>
541592Srgrimes
551592Srgrimes#include <fcntl.h>
561592Srgrimes#include <signal.h>
571592Srgrimes#include <stdio.h>
581592Srgrimes#include <stdlib.h>
591592Srgrimes#include <string.h>
601592Srgrimes#include <syslog.h>
611592Srgrimes#include <time.h>
621592Srgrimes#include <unistd.h>
631592Srgrimes#include "defs.h"
641592Srgrimes
651592Srgrimes/*
661592Srgrimes**  DispPkt -- Display the contents of an RMPCONN packet.
671592Srgrimes**
681592Srgrimes**	Parameters:
691592Srgrimes**		rconn - packet to be displayed.
701592Srgrimes**		direct - direction packet is going (DIR_*).
711592Srgrimes**
721592Srgrimes**	Returns:
731592Srgrimes**		Nothing.
741592Srgrimes**
751592Srgrimes**	Side Effects:
761592Srgrimes**		None.
771592Srgrimes*/
781592Srgrimesvoid
791592SrgrimesDispPkt(rconn, direct)
801592Srgrimes	RMPCONN *rconn;
811592Srgrimes	int direct;
821592Srgrimes{
831592Srgrimes	static char BootFmt[] = "\t\tRetCode:%u SeqNo:%lx SessID:%x Vers:%u";
841592Srgrimes	static char ReadFmt[] = "\t\tRetCode:%u Offset:%lx SessID:%x\n";
851592Srgrimes
861592Srgrimes	struct tm *tmp;
8727079Ssteve	struct rmp_packet *rmp;
881592Srgrimes	int i, omask;
8927074Ssteve	u_int32_t t;
901592Srgrimes
911592Srgrimes	/*
921592Srgrimes	 *  Since we will be working with RmpConns as well as DbgFp, we
931592Srgrimes	 *  must block signals that can affect either.
941592Srgrimes	 */
951592Srgrimes	omask = sigblock(sigmask(SIGHUP)|sigmask(SIGUSR1)|sigmask(SIGUSR2));
961592Srgrimes
971592Srgrimes	if (DbgFp == NULL) {			/* sanity */
981592Srgrimes		(void) sigsetmask(omask);
991592Srgrimes		return;
1001592Srgrimes	}
1011592Srgrimes
1021592Srgrimes	/* display direction packet is going using '>>>' or '<<<' */
1031592Srgrimes	fputs((direct==DIR_RCVD)?"<<< ":(direct==DIR_SENT)?">>> ":"", DbgFp);
1041592Srgrimes
1051592Srgrimes	/* display packet timestamp */
1061592Srgrimes	tmp = localtime((time_t *)&rconn->tstamp.tv_sec);
1071592Srgrimes	fprintf(DbgFp, "%02d:%02d:%02d.%06ld   ", tmp->tm_hour, tmp->tm_min,
1081592Srgrimes	        tmp->tm_sec, rconn->tstamp.tv_usec);
1091592Srgrimes
1101592Srgrimes	/* display src or dst addr and information about network interface */
1111592Srgrimes	fprintf(DbgFp, "Addr: %s   Intf: %s\n", EnetStr(rconn), IntfName);
1121592Srgrimes
1131592Srgrimes	rmp = &rconn->rmp;
1141592Srgrimes
1151592Srgrimes	/* display IEEE 802.2 Logical Link Control header */
1161592Srgrimes	(void) fprintf(DbgFp, "\t802.2 LLC: DSAP:%x SSAP:%x CTRL:%x\n",
11727074Ssteve               rmp->hp_llc.dsap, rmp->hp_llc.ssap, ntohs(rmp->hp_llc.cntrl));
1181592Srgrimes
1191592Srgrimes	/* display HP extensions to 802.2 Logical Link Control header */
1201592Srgrimes	(void) fprintf(DbgFp, "\tHP Ext:    DXSAP:%x SXSAP:%x\n",
12127074Ssteve	               ntohs(rmp->hp_llc.dxsap), ntohs(rmp->hp_llc.sxsap));
1221592Srgrimes
1231592Srgrimes	/*
1241592Srgrimes	 *  Display information about RMP packet using type field to
1251592Srgrimes	 *  determine what kind of packet this is.
1261592Srgrimes	 */
1271592Srgrimes	switch(rmp->r_type) {
1281592Srgrimes		case RMP_BOOT_REQ:		/* boot request */
1291592Srgrimes			(void) fprintf(DbgFp, "\tBoot Request:");
1301592Srgrimes			GETWORD(rmp->r_brq.rmp_seqno, t);
13127074Ssteve			if (ntohs(rmp->r_brq.rmp_session) == RMP_PROBESID) {
1321592Srgrimes				if (WORDZE(rmp->r_brq.rmp_seqno))
1331592Srgrimes					fputs(" (Send Server ID)", DbgFp);
1341592Srgrimes				else
1351592Srgrimes					fprintf(DbgFp," (Send Filename #%u)",t);
1361592Srgrimes			}
1371592Srgrimes			(void) fputc('\n', DbgFp);
1381592Srgrimes			(void) fprintf(DbgFp, BootFmt, rmp->r_brq.rmp_retcode,
13927074Ssteve			        t, ntohs(rmp->r_brq.rmp_session),
14027074Ssteve			        ntohs(rmp->r_brq.rmp_version));
1411592Srgrimes			(void) fprintf(DbgFp, "\n\t\tMachine Type: ");
1421592Srgrimes			for (i = 0; i < RMP_MACHLEN; i++)
1431592Srgrimes				(void) fputc(rmp->r_brq.rmp_machtype[i], DbgFp);
1441592Srgrimes			DspFlnm(rmp->r_brq.rmp_flnmsize, &rmp->r_brq.rmp_flnm);
1451592Srgrimes			break;
1461592Srgrimes		case RMP_BOOT_REPL:		/* boot reply */
1471592Srgrimes			fprintf(DbgFp, "\tBoot Reply:\n");
1481592Srgrimes			GETWORD(rmp->r_brpl.rmp_seqno, t);
1491592Srgrimes			(void) fprintf(DbgFp, BootFmt, rmp->r_brpl.rmp_retcode,
15027074Ssteve			        t, ntohs(rmp->r_brpl.rmp_session),
15127074Ssteve			        ntohs(rmp->r_brpl.rmp_version));
1521592Srgrimes			DspFlnm(rmp->r_brpl.rmp_flnmsize,&rmp->r_brpl.rmp_flnm);
1531592Srgrimes			break;
1541592Srgrimes		case RMP_READ_REQ:		/* read request */
1551592Srgrimes			(void) fprintf(DbgFp, "\tRead Request:\n");
1561592Srgrimes			GETWORD(rmp->r_rrq.rmp_offset, t);
1571592Srgrimes			(void) fprintf(DbgFp, ReadFmt, rmp->r_rrq.rmp_retcode,
15827074Ssteve			        t, ntohs(rmp->r_rrq.rmp_session));
1591592Srgrimes			(void) fprintf(DbgFp, "\t\tNoOfBytes: %u\n",
16027074Ssteve			        ntohs(rmp->r_rrq.rmp_size));
1611592Srgrimes			break;
1621592Srgrimes		case RMP_READ_REPL:		/* read reply */
1631592Srgrimes			(void) fprintf(DbgFp, "\tRead Reply:\n");
1641592Srgrimes			GETWORD(rmp->r_rrpl.rmp_offset, t);
1651592Srgrimes			(void) fprintf(DbgFp, ReadFmt, rmp->r_rrpl.rmp_retcode,
16627074Ssteve			        t, ntohs(rmp->r_rrpl.rmp_session));
1671592Srgrimes			(void) fprintf(DbgFp, "\t\tNoOfBytesSent: %d\n",
1681592Srgrimes			        rconn->rmplen - RMPREADSIZE(0));
1691592Srgrimes			break;
1701592Srgrimes		case RMP_BOOT_DONE:		/* boot complete */
1711592Srgrimes			(void) fprintf(DbgFp, "\tBoot Complete:\n");
1721592Srgrimes			(void) fprintf(DbgFp, "\t\tRetCode:%u SessID:%x\n",
1731592Srgrimes			        rmp->r_done.rmp_retcode,
17427074Ssteve			        ntohs(rmp->r_done.rmp_session));
1751592Srgrimes			break;
1761592Srgrimes		default:			/* ??? */
1771592Srgrimes			(void) fprintf(DbgFp, "\tUnknown Type:(%d)\n",
1781592Srgrimes				rmp->r_type);
1791592Srgrimes	}
1801592Srgrimes	(void) fputc('\n', DbgFp);
1811592Srgrimes	(void) fflush(DbgFp);
1821592Srgrimes
1831592Srgrimes	(void) sigsetmask(omask);		/* reset old signal mask */
1841592Srgrimes}
1851592Srgrimes
1861592Srgrimes
1871592Srgrimes/*
1881592Srgrimes**  GetEtherAddr -- convert an RMP (Ethernet) address into a string.
1891592Srgrimes**
1901592Srgrimes**	An RMP BOOT packet has been received.  Look at the type field
1911592Srgrimes**	and process Boot Requests, Read Requests, and Boot Complete
1921592Srgrimes**	packets.  Any other type will be dropped with a warning msg.
1931592Srgrimes**
1941592Srgrimes**	Parameters:
1951592Srgrimes**		addr - array of RMP_ADDRLEN bytes.
1961592Srgrimes**
1971592Srgrimes**	Returns:
1981592Srgrimes**		Pointer to static string representation of `addr'.
1991592Srgrimes**
2001592Srgrimes**	Side Effects:
2011592Srgrimes**		None.
2021592Srgrimes**
2031592Srgrimes**	Warnings:
2041592Srgrimes**		- The return value points to a static buffer; it must
2051592Srgrimes**		  be copied if it's to be saved.
2061592Srgrimes*/
2071592Srgrimeschar *
2081592SrgrimesGetEtherAddr(addr)
20927074Ssteve	u_int8_t *addr;
2101592Srgrimes{
2111592Srgrimes	static char Hex[] = "0123456789abcdef";
2121592Srgrimes	static char etherstr[RMP_ADDRLEN*3];
21327079Ssteve	int i;
21427079Ssteve	char *cp;
2151592Srgrimes
2161592Srgrimes	/*
2171592Srgrimes	 *  For each byte in `addr', convert it to "<hexchar><hexchar>:".
2181592Srgrimes	 *  The last byte does not get a trailing `:' appended.
2191592Srgrimes	 */
2201592Srgrimes	i = 0;
22127074Ssteve	cp = etherstr;
2221592Srgrimes	for(;;) {
22327074Ssteve		*cp++ = Hex[*addr >> 4 & 0xf];
22427074Ssteve		*cp++ = Hex[*addr++ & 0xf];
2251592Srgrimes		if (++i == RMP_ADDRLEN)
2261592Srgrimes			break;
22727074Ssteve		*cp++ = ':';
2281592Srgrimes	}
22927074Ssteve	*cp = '\0';
2301592Srgrimes
2311592Srgrimes	return(etherstr);
2321592Srgrimes}
2331592Srgrimes
2341592Srgrimes
2351592Srgrimes/*
2361592Srgrimes**  DispFlnm -- Print a string of bytes to DbgFp (often, a file name).
2371592Srgrimes**
2381592Srgrimes**	Parameters:
2391592Srgrimes**		size - number of bytes to print.
2401592Srgrimes**		flnm - address of first byte.
2411592Srgrimes**
2421592Srgrimes**	Returns:
2431592Srgrimes**		Nothing.
2441592Srgrimes**
2451592Srgrimes**	Side Effects:
2461592Srgrimes**		- Characters are sent to `DbgFp'.
2471592Srgrimes*/
2481592Srgrimesvoid
2491592SrgrimesDspFlnm(size, flnm)
25027079Ssteve	u_int size;
25127079Ssteve	char *flnm;
2521592Srgrimes{
25327079Ssteve	int i;
2541592Srgrimes
25527074Ssteve	(void) fprintf(DbgFp, "\n\t\tFile Name (%u): <", size);
2561592Srgrimes	for (i = 0; i < size; i++)
2571592Srgrimes		(void) fputc(*flnm++, DbgFp);
2581592Srgrimes	(void) fputs(">\n", DbgFp);
2591592Srgrimes}
2601592Srgrimes
2611592Srgrimes
2621592Srgrimes/*
2631592Srgrimes**  NewClient -- allocate memory for a new CLIENT.
2641592Srgrimes**
2651592Srgrimes**	Parameters:
2661592Srgrimes**		addr - RMP (Ethernet) address of new client.
2671592Srgrimes**
2681592Srgrimes**	Returns:
2691592Srgrimes**		Ptr to new CLIENT or NULL if we ran out of memory.
2701592Srgrimes**
2711592Srgrimes**	Side Effects:
2721592Srgrimes**		- Memory will be malloc'd for the new CLIENT.
2731592Srgrimes**		- If malloc() fails, a log message will be generated.
2741592Srgrimes*/
2751592SrgrimesCLIENT *
2761592SrgrimesNewClient(addr)
27727074Ssteve	u_int8_t *addr;
2781592Srgrimes{
2791592Srgrimes	CLIENT *ctmp;
2801592Srgrimes
2811592Srgrimes	if ((ctmp = (CLIENT *) malloc(sizeof(CLIENT))) == NULL) {
2821592Srgrimes		syslog(LOG_ERR, "NewClient: out of memory (%s)",
2831592Srgrimes		       GetEtherAddr(addr));
2841592Srgrimes		return(NULL);
2851592Srgrimes	}
2861592Srgrimes
28727079Ssteve	memset(ctmp, 0, sizeof(CLIENT));
28827079Ssteve	memmove(&ctmp->addr[0], addr, RMP_ADDRLEN);
2891592Srgrimes	return(ctmp);
2901592Srgrimes}
2911592Srgrimes
2921592Srgrimes/*
2931592Srgrimes**  FreeClient -- free linked list of Clients.
2941592Srgrimes**
2951592Srgrimes**	Parameters:
2961592Srgrimes**		None.
2971592Srgrimes**
2981592Srgrimes**	Returns:
2991592Srgrimes**		Nothing.
3001592Srgrimes**
3011592Srgrimes**	Side Effects:
3021592Srgrimes**		- All malloc'd memory associated with the linked list of
3031592Srgrimes**		  CLIENTS will be free'd; `Clients' will be set to NULL.
3041592Srgrimes**
3051592Srgrimes**	Warnings:
3061592Srgrimes**		- This routine must be called with SIGHUP blocked.
3071592Srgrimes*/
3081592Srgrimesvoid
3091592SrgrimesFreeClients()
3101592Srgrimes{
31127079Ssteve	CLIENT *ctmp;
3121592Srgrimes
3131592Srgrimes	while (Clients != NULL) {
3141592Srgrimes		ctmp = Clients;
3151592Srgrimes		Clients = Clients->next;
3161592Srgrimes		FreeClient(ctmp);
3171592Srgrimes	}
3181592Srgrimes}
3191592Srgrimes
3201592Srgrimes/*
3211592Srgrimes**  NewStr -- allocate memory for a character array.
3221592Srgrimes**
3231592Srgrimes**	Parameters:
3241592Srgrimes**		str - null terminated character array.
3251592Srgrimes**
3261592Srgrimes**	Returns:
3271592Srgrimes**		Ptr to new character array or NULL if we ran out of memory.
3281592Srgrimes**
3291592Srgrimes**	Side Effects:
3301592Srgrimes**		- Memory will be malloc'd for the new character array.
3311592Srgrimes**		- If malloc() fails, a log message will be generated.
3321592Srgrimes*/
3331592Srgrimeschar *
3341592SrgrimesNewStr(str)
3351592Srgrimes	char *str;
3361592Srgrimes{
3371592Srgrimes	char *stmp;
3381592Srgrimes
3391592Srgrimes	if ((stmp = (char *)malloc((unsigned) (strlen(str)+1))) == NULL) {
3401592Srgrimes		syslog(LOG_ERR, "NewStr: out of memory (%s)", str);
3411592Srgrimes		return(NULL);
3421592Srgrimes	}
3431592Srgrimes
3441592Srgrimes	(void) strcpy(stmp, str);
3451592Srgrimes	return(stmp);
3461592Srgrimes}
3471592Srgrimes
3481592Srgrimes/*
3491592Srgrimes**  To save time, NewConn and FreeConn maintain a cache of one RMPCONN
3501592Srgrimes**  in `LastFree' (defined below).
3511592Srgrimes*/
3521592Srgrimes
3531592Srgrimesstatic RMPCONN *LastFree = NULL;
3541592Srgrimes
3551592Srgrimes/*
3561592Srgrimes**  NewConn -- allocate memory for a new RMPCONN connection.
3571592Srgrimes**
3581592Srgrimes**	Parameters:
3591592Srgrimes**		rconn - initialization template for new connection.
3601592Srgrimes**
3611592Srgrimes**	Returns:
3621592Srgrimes**		Ptr to new RMPCONN or NULL if we ran out of memory.
3631592Srgrimes**
3641592Srgrimes**	Side Effects:
3651592Srgrimes**		- Memory may be malloc'd for the new RMPCONN (if not cached).
3661592Srgrimes**		- If malloc() fails, a log message will be generated.
3671592Srgrimes*/
3681592SrgrimesRMPCONN *
3691592SrgrimesNewConn(rconn)
3701592Srgrimes	RMPCONN *rconn;
3711592Srgrimes{
3721592Srgrimes	RMPCONN *rtmp;
3731592Srgrimes
3741592Srgrimes	if (LastFree == NULL) {		/* nothing cached; make a new one */
3751592Srgrimes		if ((rtmp = (RMPCONN *) malloc(sizeof(RMPCONN))) == NULL) {
3761592Srgrimes			syslog(LOG_ERR, "NewConn: out of memory (%s)",
3771592Srgrimes			       EnetStr(rconn));
3781592Srgrimes			return(NULL);
3791592Srgrimes		}
3801592Srgrimes	} else {			/* use the cached RMPCONN */
3811592Srgrimes		rtmp = LastFree;
3821592Srgrimes		LastFree = NULL;
3831592Srgrimes	}
3841592Srgrimes
3851592Srgrimes	/*
3861592Srgrimes	 *  Copy template into `rtmp', init file descriptor to `-1' and
3871592Srgrimes	 *  set ptr to next elem NULL.
3881592Srgrimes	 */
38927079Ssteve	memmove((char *)rtmp, (char *)rconn, sizeof(RMPCONN));
3901592Srgrimes	rtmp->bootfd = -1;
3911592Srgrimes	rtmp->next = NULL;
3921592Srgrimes
3931592Srgrimes	return(rtmp);
3941592Srgrimes}
3951592Srgrimes
3961592Srgrimes/*
3971592Srgrimes**  FreeConn -- Free memory associated with an RMPCONN connection.
3981592Srgrimes**
3991592Srgrimes**	Parameters:
4001592Srgrimes**		rtmp - ptr to RMPCONN to be free'd.
4011592Srgrimes**
4021592Srgrimes**	Returns:
4031592Srgrimes**		Nothing.
4041592Srgrimes**
4051592Srgrimes**	Side Effects:
4061592Srgrimes**		- Memory associated with `rtmp' may be free'd (or cached).
4071592Srgrimes**		- File desc associated with `rtmp->bootfd' will be closed.
4081592Srgrimes*/
4091592Srgrimesvoid
4101592SrgrimesFreeConn(rtmp)
41127079Ssteve	RMPCONN *rtmp;
4121592Srgrimes{
4131592Srgrimes	/*
4141592Srgrimes	 *  If the file descriptor is in use, close the file.
4151592Srgrimes	 */
4161592Srgrimes	if (rtmp->bootfd >= 0) {
4171592Srgrimes		(void) close(rtmp->bootfd);
4181592Srgrimes		rtmp->bootfd = -1;
4191592Srgrimes	}
4201592Srgrimes
4211592Srgrimes	if (LastFree == NULL)		/* cache for next time */
4221592Srgrimes		rtmp = LastFree;
4231592Srgrimes	else				/* already one cached; free this one */
4241592Srgrimes		free((char *)rtmp);
4251592Srgrimes}
4261592Srgrimes
4271592Srgrimes/*
4281592Srgrimes**  FreeConns -- free linked list of RMPCONN connections.
4291592Srgrimes**
4301592Srgrimes**	Parameters:
4311592Srgrimes**		None.
4321592Srgrimes**
4331592Srgrimes**	Returns:
4341592Srgrimes**		Nothing.
4351592Srgrimes**
4361592Srgrimes**	Side Effects:
4371592Srgrimes**		- All malloc'd memory associated with the linked list of
4381592Srgrimes**		  connections will be free'd; `RmpConns' will be set to NULL.
4391592Srgrimes**		- If LastFree is != NULL, it too will be free'd & NULL'd.
4401592Srgrimes**
4411592Srgrimes**	Warnings:
4421592Srgrimes**		- This routine must be called with SIGHUP blocked.
4431592Srgrimes*/
4441592Srgrimesvoid
4451592SrgrimesFreeConns()
4461592Srgrimes{
44727079Ssteve	RMPCONN *rtmp;
4481592Srgrimes
4491592Srgrimes	while (RmpConns != NULL) {
4501592Srgrimes		rtmp = RmpConns;
4511592Srgrimes		RmpConns = RmpConns->next;
4521592Srgrimes		FreeConn(rtmp);
4531592Srgrimes	}
4541592Srgrimes
4551592Srgrimes	if (LastFree != NULL) {
4561592Srgrimes		free((char *)LastFree);
4571592Srgrimes		LastFree = NULL;
4581592Srgrimes	}
4591592Srgrimes}
4601592Srgrimes
4611592Srgrimes/*
4621592Srgrimes**  AddConn -- Add a connection to the linked list of connections.
4631592Srgrimes**
4641592Srgrimes**	Parameters:
4651592Srgrimes**		rconn - connection to be added.
4661592Srgrimes**
4671592Srgrimes**	Returns:
4681592Srgrimes**		Nothing.
4691592Srgrimes**
4701592Srgrimes**	Side Effects:
4711592Srgrimes**		- RmpConn will point to new connection.
4721592Srgrimes**
4731592Srgrimes**	Warnings:
4741592Srgrimes**		- This routine must be called with SIGHUP blocked.
4751592Srgrimes*/
4761592Srgrimesvoid
4771592SrgrimesAddConn(rconn)
47827079Ssteve	RMPCONN *rconn;
4791592Srgrimes{
4801592Srgrimes	if (RmpConns != NULL)
4811592Srgrimes		rconn->next = RmpConns;
4821592Srgrimes	RmpConns = rconn;
4831592Srgrimes}
4841592Srgrimes
4851592Srgrimes/*
4861592Srgrimes**  FindConn -- Find a connection in the linked list of connections.
4871592Srgrimes**
4881592Srgrimes**	We use the RMP (Ethernet) address as the basis for determining
4891592Srgrimes**	if this is the same connection.  According to the Remote Maint
4901592Srgrimes**	Protocol, we can only have one connection with any machine.
4911592Srgrimes**
4921592Srgrimes**	Parameters:
4931592Srgrimes**		rconn - connection to be found.
4941592Srgrimes**
4951592Srgrimes**	Returns:
4961592Srgrimes**		Matching connection from linked list or NULL if not found.
4971592Srgrimes**
4981592Srgrimes**	Side Effects:
4991592Srgrimes**		None.
5001592Srgrimes**
5011592Srgrimes**	Warnings:
5021592Srgrimes**		- This routine must be called with SIGHUP blocked.
5031592Srgrimes*/
5041592SrgrimesRMPCONN *
5051592SrgrimesFindConn(rconn)
50627079Ssteve	RMPCONN *rconn;
5071592Srgrimes{
50827079Ssteve	RMPCONN *rtmp;
5091592Srgrimes
5101592Srgrimes	for (rtmp = RmpConns; rtmp != NULL; rtmp = rtmp->next)
5111592Srgrimes		if (bcmp((char *)&rconn->rmp.hp_hdr.saddr[0],
5121592Srgrimes		         (char *)&rtmp->rmp.hp_hdr.saddr[0], RMP_ADDRLEN) == 0)
5131592Srgrimes			break;
5141592Srgrimes
5151592Srgrimes	return(rtmp);
5161592Srgrimes}
5171592Srgrimes
5181592Srgrimes/*
5191592Srgrimes**  RemoveConn -- Remove a connection from the linked list of connections.
5201592Srgrimes**
5211592Srgrimes**	Parameters:
5221592Srgrimes**		rconn - connection to be removed.
5231592Srgrimes**
5241592Srgrimes**	Returns:
5251592Srgrimes**		Nothing.
5261592Srgrimes**
5271592Srgrimes**	Side Effects:
5281592Srgrimes**		- If found, an RMPCONN will cease to exist and it will
5291592Srgrimes**		  be removed from the linked list.
5301592Srgrimes**
5311592Srgrimes**	Warnings:
5321592Srgrimes**		- This routine must be called with SIGHUP blocked.
5331592Srgrimes*/
5341592Srgrimesvoid
5351592SrgrimesRemoveConn(rconn)
53627079Ssteve	RMPCONN *rconn;
5371592Srgrimes{
53827079Ssteve	RMPCONN *thisrconn, *lastrconn;
5391592Srgrimes
5401592Srgrimes	if (RmpConns == rconn) {		/* easy case */
5411592Srgrimes		RmpConns = RmpConns->next;
5421592Srgrimes		FreeConn(rconn);
5431592Srgrimes	} else {				/* must traverse linked list */
5441592Srgrimes		lastrconn = RmpConns;			/* set back ptr */
5451592Srgrimes		thisrconn = lastrconn->next;		/* set current ptr */
5461592Srgrimes		while (thisrconn != NULL) {
5471592Srgrimes			if (rconn == thisrconn) {		/* found it */
5481592Srgrimes				lastrconn->next = thisrconn->next;
5491592Srgrimes				FreeConn(thisrconn);
5501592Srgrimes				break;
5511592Srgrimes			}
5521592Srgrimes			lastrconn = thisrconn;
5531592Srgrimes			thisrconn = thisrconn->next;
5541592Srgrimes		}
5551592Srgrimes	}
5561592Srgrimes}
557