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
421592Srgrimes *
4327074Ssteve * From: Utah Hdr: utils.c 3.1 92/07/06
441592Srgrimes * Author: Jeff Forys, University of Utah CSS
451592Srgrimes */
461592Srgrimes
471592Srgrimes#ifndef lint
4831386Scharnier#if 0
4927077Sstevestatic const char sccsid[] = "@(#)utils.c	8.1 (Berkeley) 6/4/93";
5031386Scharnier#endif
5131386Scharnierstatic const char rcsid[] =
5250476Speter  "$FreeBSD$";
531592Srgrimes#endif /* not lint */
541592Srgrimes
551592Srgrimes#include <sys/param.h>
5627077Ssteve#include <sys/time.h>
57129652Sstefanf#include <netinet/in.h>
581592Srgrimes
591592Srgrimes#include <fcntl.h>
601592Srgrimes#include <signal.h>
611592Srgrimes#include <stdio.h>
621592Srgrimes#include <stdlib.h>
631592Srgrimes#include <string.h>
641592Srgrimes#include <syslog.h>
651592Srgrimes#include <time.h>
661592Srgrimes#include <unistd.h>
671592Srgrimes#include "defs.h"
681592Srgrimes
691592Srgrimes/*
701592Srgrimes**  DispPkt -- Display the contents of an RMPCONN packet.
711592Srgrimes**
721592Srgrimes**	Parameters:
731592Srgrimes**		rconn - packet to be displayed.
741592Srgrimes**		direct - direction packet is going (DIR_*).
751592Srgrimes**
761592Srgrimes**	Returns:
771592Srgrimes**		Nothing.
781592Srgrimes**
791592Srgrimes**	Side Effects:
801592Srgrimes**		None.
811592Srgrimes*/
821592Srgrimesvoid
8390377SimpDispPkt(RMPCONN *rconn, int direct)
841592Srgrimes{
85229140Sdim	static const char BootFmt[] = "\t\tRetCode:%u SeqNo:%x SessID:%x Vers:%u";
86229140Sdim	static const char ReadFmt[] = "\t\tRetCode:%u Offset:%x SessID:%x\n";
871592Srgrimes
881592Srgrimes	struct tm *tmp;
8927079Ssteve	struct rmp_packet *rmp;
901592Srgrimes	int i, omask;
9127074Ssteve	u_int32_t t;
921592Srgrimes
931592Srgrimes	/*
941592Srgrimes	 *  Since we will be working with RmpConns as well as DbgFp, we
951592Srgrimes	 *  must block signals that can affect either.
961592Srgrimes	 */
971592Srgrimes	omask = sigblock(sigmask(SIGHUP)|sigmask(SIGUSR1)|sigmask(SIGUSR2));
981592Srgrimes
991592Srgrimes	if (DbgFp == NULL) {			/* sanity */
1001592Srgrimes		(void) sigsetmask(omask);
1011592Srgrimes		return;
1021592Srgrimes	}
1031592Srgrimes
1041592Srgrimes	/* display direction packet is going using '>>>' or '<<<' */
1051592Srgrimes	fputs((direct==DIR_RCVD)?"<<< ":(direct==DIR_SENT)?">>> ":"", DbgFp);
1061592Srgrimes
1071592Srgrimes	/* display packet timestamp */
1081592Srgrimes	tmp = localtime((time_t *)&rconn->tstamp.tv_sec);
1091592Srgrimes	fprintf(DbgFp, "%02d:%02d:%02d.%06ld   ", tmp->tm_hour, tmp->tm_min,
1101592Srgrimes	        tmp->tm_sec, rconn->tstamp.tv_usec);
1111592Srgrimes
1121592Srgrimes	/* display src or dst addr and information about network interface */
1131592Srgrimes	fprintf(DbgFp, "Addr: %s   Intf: %s\n", EnetStr(rconn), IntfName);
1141592Srgrimes
1151592Srgrimes	rmp = &rconn->rmp;
1161592Srgrimes
1171592Srgrimes	/* display IEEE 802.2 Logical Link Control header */
1181592Srgrimes	(void) fprintf(DbgFp, "\t802.2 LLC: DSAP:%x SSAP:%x CTRL:%x\n",
11927074Ssteve               rmp->hp_llc.dsap, rmp->hp_llc.ssap, ntohs(rmp->hp_llc.cntrl));
1201592Srgrimes
1211592Srgrimes	/* display HP extensions to 802.2 Logical Link Control header */
1221592Srgrimes	(void) fprintf(DbgFp, "\tHP Ext:    DXSAP:%x SXSAP:%x\n",
12327074Ssteve	               ntohs(rmp->hp_llc.dxsap), ntohs(rmp->hp_llc.sxsap));
1241592Srgrimes
1251592Srgrimes	/*
1261592Srgrimes	 *  Display information about RMP packet using type field to
1271592Srgrimes	 *  determine what kind of packet this is.
1281592Srgrimes	 */
1291592Srgrimes	switch(rmp->r_type) {
1301592Srgrimes		case RMP_BOOT_REQ:		/* boot request */
1311592Srgrimes			(void) fprintf(DbgFp, "\tBoot Request:");
1321592Srgrimes			GETWORD(rmp->r_brq.rmp_seqno, t);
13327074Ssteve			if (ntohs(rmp->r_brq.rmp_session) == RMP_PROBESID) {
1341592Srgrimes				if (WORDZE(rmp->r_brq.rmp_seqno))
1351592Srgrimes					fputs(" (Send Server ID)", DbgFp);
1361592Srgrimes				else
1371592Srgrimes					fprintf(DbgFp," (Send Filename #%u)",t);
1381592Srgrimes			}
1391592Srgrimes			(void) fputc('\n', DbgFp);
1401592Srgrimes			(void) fprintf(DbgFp, BootFmt, rmp->r_brq.rmp_retcode,
14127074Ssteve			        t, ntohs(rmp->r_brq.rmp_session),
14227074Ssteve			        ntohs(rmp->r_brq.rmp_version));
1431592Srgrimes			(void) fprintf(DbgFp, "\n\t\tMachine Type: ");
1441592Srgrimes			for (i = 0; i < RMP_MACHLEN; i++)
1451592Srgrimes				(void) fputc(rmp->r_brq.rmp_machtype[i], DbgFp);
1461592Srgrimes			DspFlnm(rmp->r_brq.rmp_flnmsize, &rmp->r_brq.rmp_flnm);
1471592Srgrimes			break;
1481592Srgrimes		case RMP_BOOT_REPL:		/* boot reply */
1491592Srgrimes			fprintf(DbgFp, "\tBoot Reply:\n");
1501592Srgrimes			GETWORD(rmp->r_brpl.rmp_seqno, t);
1511592Srgrimes			(void) fprintf(DbgFp, BootFmt, rmp->r_brpl.rmp_retcode,
15227074Ssteve			        t, ntohs(rmp->r_brpl.rmp_session),
15327074Ssteve			        ntohs(rmp->r_brpl.rmp_version));
1541592Srgrimes			DspFlnm(rmp->r_brpl.rmp_flnmsize,&rmp->r_brpl.rmp_flnm);
1551592Srgrimes			break;
1561592Srgrimes		case RMP_READ_REQ:		/* read request */
1571592Srgrimes			(void) fprintf(DbgFp, "\tRead Request:\n");
1581592Srgrimes			GETWORD(rmp->r_rrq.rmp_offset, t);
1591592Srgrimes			(void) fprintf(DbgFp, ReadFmt, rmp->r_rrq.rmp_retcode,
16027074Ssteve			        t, ntohs(rmp->r_rrq.rmp_session));
1611592Srgrimes			(void) fprintf(DbgFp, "\t\tNoOfBytes: %u\n",
16227074Ssteve			        ntohs(rmp->r_rrq.rmp_size));
1631592Srgrimes			break;
1641592Srgrimes		case RMP_READ_REPL:		/* read reply */
1651592Srgrimes			(void) fprintf(DbgFp, "\tRead Reply:\n");
1661592Srgrimes			GETWORD(rmp->r_rrpl.rmp_offset, t);
1671592Srgrimes			(void) fprintf(DbgFp, ReadFmt, rmp->r_rrpl.rmp_retcode,
16827074Ssteve			        t, ntohs(rmp->r_rrpl.rmp_session));
169229140Sdim			(void) fprintf(DbgFp, "\t\tNoOfBytesSent: %zu\n",
1701592Srgrimes			        rconn->rmplen - RMPREADSIZE(0));
1711592Srgrimes			break;
1721592Srgrimes		case RMP_BOOT_DONE:		/* boot complete */
1731592Srgrimes			(void) fprintf(DbgFp, "\tBoot Complete:\n");
1741592Srgrimes			(void) fprintf(DbgFp, "\t\tRetCode:%u SessID:%x\n",
1751592Srgrimes			        rmp->r_done.rmp_retcode,
17627074Ssteve			        ntohs(rmp->r_done.rmp_session));
1771592Srgrimes			break;
1781592Srgrimes		default:			/* ??? */
1791592Srgrimes			(void) fprintf(DbgFp, "\tUnknown Type:(%d)\n",
1801592Srgrimes				rmp->r_type);
1811592Srgrimes	}
1821592Srgrimes	(void) fputc('\n', DbgFp);
1831592Srgrimes	(void) fflush(DbgFp);
1841592Srgrimes
1851592Srgrimes	(void) sigsetmask(omask);		/* reset old signal mask */
1861592Srgrimes}
1871592Srgrimes
1881592Srgrimes
1891592Srgrimes/*
1901592Srgrimes**  GetEtherAddr -- convert an RMP (Ethernet) address into a string.
1911592Srgrimes**
1921592Srgrimes**	An RMP BOOT packet has been received.  Look at the type field
1931592Srgrimes**	and process Boot Requests, Read Requests, and Boot Complete
1941592Srgrimes**	packets.  Any other type will be dropped with a warning msg.
1951592Srgrimes**
1961592Srgrimes**	Parameters:
1971592Srgrimes**		addr - array of RMP_ADDRLEN bytes.
1981592Srgrimes**
1991592Srgrimes**	Returns:
2001592Srgrimes**		Pointer to static string representation of `addr'.
2011592Srgrimes**
2021592Srgrimes**	Side Effects:
2031592Srgrimes**		None.
2041592Srgrimes**
2051592Srgrimes**	Warnings:
2061592Srgrimes**		- The return value points to a static buffer; it must
2071592Srgrimes**		  be copied if it's to be saved.
2081592Srgrimes*/
2091592Srgrimeschar *
21090377SimpGetEtherAddr(u_int8_t *addr)
2111592Srgrimes{
2121592Srgrimes	static char Hex[] = "0123456789abcdef";
2131592Srgrimes	static char etherstr[RMP_ADDRLEN*3];
21427079Ssteve	int i;
21527079Ssteve	char *cp;
2161592Srgrimes
2171592Srgrimes	/*
2181592Srgrimes	 *  For each byte in `addr', convert it to "<hexchar><hexchar>:".
2191592Srgrimes	 *  The last byte does not get a trailing `:' appended.
2201592Srgrimes	 */
2211592Srgrimes	i = 0;
22227074Ssteve	cp = etherstr;
2231592Srgrimes	for(;;) {
22427074Ssteve		*cp++ = Hex[*addr >> 4 & 0xf];
22527074Ssteve		*cp++ = Hex[*addr++ & 0xf];
2261592Srgrimes		if (++i == RMP_ADDRLEN)
2271592Srgrimes			break;
22827074Ssteve		*cp++ = ':';
2291592Srgrimes	}
23027074Ssteve	*cp = '\0';
2311592Srgrimes
2321592Srgrimes	return(etherstr);
2331592Srgrimes}
2341592Srgrimes
2351592Srgrimes
2361592Srgrimes/*
2371592Srgrimes**  DispFlnm -- Print a string of bytes to DbgFp (often, a file name).
2381592Srgrimes**
2391592Srgrimes**	Parameters:
2401592Srgrimes**		size - number of bytes to print.
2411592Srgrimes**		flnm - address of first byte.
2421592Srgrimes**
2431592Srgrimes**	Returns:
2441592Srgrimes**		Nothing.
2451592Srgrimes**
2461592Srgrimes**	Side Effects:
2471592Srgrimes**		- Characters are sent to `DbgFp'.
2481592Srgrimes*/
2491592Srgrimesvoid
25090377SimpDspFlnm(u_int size, char *flnm)
2511592Srgrimes{
25227079Ssteve	int i;
2531592Srgrimes
25427074Ssteve	(void) fprintf(DbgFp, "\n\t\tFile Name (%u): <", size);
2551592Srgrimes	for (i = 0; i < size; i++)
2561592Srgrimes		(void) fputc(*flnm++, DbgFp);
2571592Srgrimes	(void) fputs(">\n", DbgFp);
2581592Srgrimes}
2591592Srgrimes
2601592Srgrimes
2611592Srgrimes/*
2621592Srgrimes**  NewClient -- allocate memory for a new CLIENT.
2631592Srgrimes**
2641592Srgrimes**	Parameters:
2651592Srgrimes**		addr - RMP (Ethernet) address of new client.
2661592Srgrimes**
2671592Srgrimes**	Returns:
2681592Srgrimes**		Ptr to new CLIENT or NULL if we ran out of memory.
2691592Srgrimes**
2701592Srgrimes**	Side Effects:
2711592Srgrimes**		- Memory will be malloc'd for the new CLIENT.
2721592Srgrimes**		- If malloc() fails, a log message will be generated.
2731592Srgrimes*/
2741592SrgrimesCLIENT *
27590377SimpNewClient(u_int8_t *addr)
2761592Srgrimes{
2771592Srgrimes	CLIENT *ctmp;
2781592Srgrimes
2791592Srgrimes	if ((ctmp = (CLIENT *) malloc(sizeof(CLIENT))) == NULL) {
2801592Srgrimes		syslog(LOG_ERR, "NewClient: out of memory (%s)",
2811592Srgrimes		       GetEtherAddr(addr));
2821592Srgrimes		return(NULL);
2831592Srgrimes	}
2841592Srgrimes
28527079Ssteve	memset(ctmp, 0, sizeof(CLIENT));
28627079Ssteve	memmove(&ctmp->addr[0], addr, RMP_ADDRLEN);
2871592Srgrimes	return(ctmp);
2881592Srgrimes}
2891592Srgrimes
2901592Srgrimes/*
2911592Srgrimes**  FreeClient -- free linked list of Clients.
2921592Srgrimes**
2931592Srgrimes**	Parameters:
2941592Srgrimes**		None.
2951592Srgrimes**
2961592Srgrimes**	Returns:
2971592Srgrimes**		Nothing.
2981592Srgrimes**
2991592Srgrimes**	Side Effects:
3001592Srgrimes**		- All malloc'd memory associated with the linked list of
3011592Srgrimes**		  CLIENTS will be free'd; `Clients' will be set to NULL.
3021592Srgrimes**
3031592Srgrimes**	Warnings:
3041592Srgrimes**		- This routine must be called with SIGHUP blocked.
3051592Srgrimes*/
3061592Srgrimesvoid
30790377SimpFreeClients(void)
3081592Srgrimes{
30927079Ssteve	CLIENT *ctmp;
3101592Srgrimes
3111592Srgrimes	while (Clients != NULL) {
3121592Srgrimes		ctmp = Clients;
3131592Srgrimes		Clients = Clients->next;
3141592Srgrimes		FreeClient(ctmp);
3151592Srgrimes	}
3161592Srgrimes}
3171592Srgrimes
3181592Srgrimes/*
3191592Srgrimes**  NewStr -- allocate memory for a character array.
3201592Srgrimes**
3211592Srgrimes**	Parameters:
3221592Srgrimes**		str - null terminated character array.
3231592Srgrimes**
3241592Srgrimes**	Returns:
3251592Srgrimes**		Ptr to new character array or NULL if we ran out of memory.
3261592Srgrimes**
3271592Srgrimes**	Side Effects:
3281592Srgrimes**		- Memory will be malloc'd for the new character array.
3291592Srgrimes**		- If malloc() fails, a log message will be generated.
3301592Srgrimes*/
3311592Srgrimeschar *
33290377SimpNewStr(char *str)
3331592Srgrimes{
3341592Srgrimes	char *stmp;
3351592Srgrimes
3361592Srgrimes	if ((stmp = (char *)malloc((unsigned) (strlen(str)+1))) == NULL) {
3371592Srgrimes		syslog(LOG_ERR, "NewStr: out of memory (%s)", str);
3381592Srgrimes		return(NULL);
3391592Srgrimes	}
3401592Srgrimes
3411592Srgrimes	(void) strcpy(stmp, str);
3421592Srgrimes	return(stmp);
3431592Srgrimes}
3441592Srgrimes
3451592Srgrimes/*
3461592Srgrimes**  To save time, NewConn and FreeConn maintain a cache of one RMPCONN
3471592Srgrimes**  in `LastFree' (defined below).
3481592Srgrimes*/
3491592Srgrimes
3501592Srgrimesstatic RMPCONN *LastFree = NULL;
3511592Srgrimes
3521592Srgrimes/*
3531592Srgrimes**  NewConn -- allocate memory for a new RMPCONN connection.
3541592Srgrimes**
3551592Srgrimes**	Parameters:
3561592Srgrimes**		rconn - initialization template for new connection.
3571592Srgrimes**
3581592Srgrimes**	Returns:
3591592Srgrimes**		Ptr to new RMPCONN or NULL if we ran out of memory.
3601592Srgrimes**
3611592Srgrimes**	Side Effects:
3621592Srgrimes**		- Memory may be malloc'd for the new RMPCONN (if not cached).
3631592Srgrimes**		- If malloc() fails, a log message will be generated.
3641592Srgrimes*/
3651592SrgrimesRMPCONN *
36690377SimpNewConn(RMPCONN *rconn)
3671592Srgrimes{
3681592Srgrimes	RMPCONN *rtmp;
3691592Srgrimes
3701592Srgrimes	if (LastFree == NULL) {		/* nothing cached; make a new one */
3711592Srgrimes		if ((rtmp = (RMPCONN *) malloc(sizeof(RMPCONN))) == NULL) {
3721592Srgrimes			syslog(LOG_ERR, "NewConn: out of memory (%s)",
3731592Srgrimes			       EnetStr(rconn));
3741592Srgrimes			return(NULL);
3751592Srgrimes		}
3761592Srgrimes	} else {			/* use the cached RMPCONN */
3771592Srgrimes		rtmp = LastFree;
3781592Srgrimes		LastFree = NULL;
3791592Srgrimes	}
3801592Srgrimes
3811592Srgrimes	/*
3821592Srgrimes	 *  Copy template into `rtmp', init file descriptor to `-1' and
3831592Srgrimes	 *  set ptr to next elem NULL.
3841592Srgrimes	 */
38527079Ssteve	memmove((char *)rtmp, (char *)rconn, sizeof(RMPCONN));
3861592Srgrimes	rtmp->bootfd = -1;
3871592Srgrimes	rtmp->next = NULL;
3881592Srgrimes
3891592Srgrimes	return(rtmp);
3901592Srgrimes}
3911592Srgrimes
3921592Srgrimes/*
3931592Srgrimes**  FreeConn -- Free memory associated with an RMPCONN connection.
3941592Srgrimes**
3951592Srgrimes**	Parameters:
3961592Srgrimes**		rtmp - ptr to RMPCONN to be free'd.
3971592Srgrimes**
3981592Srgrimes**	Returns:
3991592Srgrimes**		Nothing.
4001592Srgrimes**
4011592Srgrimes**	Side Effects:
4021592Srgrimes**		- Memory associated with `rtmp' may be free'd (or cached).
4031592Srgrimes**		- File desc associated with `rtmp->bootfd' will be closed.
4041592Srgrimes*/
4051592Srgrimesvoid
40690377SimpFreeConn(RMPCONN *rtmp)
4071592Srgrimes{
4081592Srgrimes	/*
4091592Srgrimes	 *  If the file descriptor is in use, close the file.
4101592Srgrimes	 */
4111592Srgrimes	if (rtmp->bootfd >= 0) {
4121592Srgrimes		(void) close(rtmp->bootfd);
4131592Srgrimes		rtmp->bootfd = -1;
4141592Srgrimes	}
4151592Srgrimes
4161592Srgrimes	if (LastFree == NULL)		/* cache for next time */
4171592Srgrimes		rtmp = LastFree;
4181592Srgrimes	else				/* already one cached; free this one */
4191592Srgrimes		free((char *)rtmp);
4201592Srgrimes}
4211592Srgrimes
4221592Srgrimes/*
4231592Srgrimes**  FreeConns -- free linked list of RMPCONN connections.
4241592Srgrimes**
4251592Srgrimes**	Parameters:
4261592Srgrimes**		None.
4271592Srgrimes**
4281592Srgrimes**	Returns:
4291592Srgrimes**		Nothing.
4301592Srgrimes**
4311592Srgrimes**	Side Effects:
4321592Srgrimes**		- All malloc'd memory associated with the linked list of
4331592Srgrimes**		  connections will be free'd; `RmpConns' will be set to NULL.
4341592Srgrimes**		- If LastFree is != NULL, it too will be free'd & NULL'd.
4351592Srgrimes**
4361592Srgrimes**	Warnings:
4371592Srgrimes**		- This routine must be called with SIGHUP blocked.
4381592Srgrimes*/
4391592Srgrimesvoid
44090377SimpFreeConns(void)
4411592Srgrimes{
44227079Ssteve	RMPCONN *rtmp;
4431592Srgrimes
4441592Srgrimes	while (RmpConns != NULL) {
4451592Srgrimes		rtmp = RmpConns;
4461592Srgrimes		RmpConns = RmpConns->next;
4471592Srgrimes		FreeConn(rtmp);
4481592Srgrimes	}
4491592Srgrimes
4501592Srgrimes	if (LastFree != NULL) {
4511592Srgrimes		free((char *)LastFree);
4521592Srgrimes		LastFree = NULL;
4531592Srgrimes	}
4541592Srgrimes}
4551592Srgrimes
4561592Srgrimes/*
4571592Srgrimes**  AddConn -- Add a connection to the linked list of connections.
4581592Srgrimes**
4591592Srgrimes**	Parameters:
4601592Srgrimes**		rconn - connection to be added.
4611592Srgrimes**
4621592Srgrimes**	Returns:
4631592Srgrimes**		Nothing.
4641592Srgrimes**
4651592Srgrimes**	Side Effects:
4661592Srgrimes**		- RmpConn will point to new connection.
4671592Srgrimes**
4681592Srgrimes**	Warnings:
4691592Srgrimes**		- This routine must be called with SIGHUP blocked.
4701592Srgrimes*/
4711592Srgrimesvoid
47290377SimpAddConn(RMPCONN *rconn)
4731592Srgrimes{
4741592Srgrimes	if (RmpConns != NULL)
4751592Srgrimes		rconn->next = RmpConns;
4761592Srgrimes	RmpConns = rconn;
4771592Srgrimes}
4781592Srgrimes
4791592Srgrimes/*
4801592Srgrimes**  FindConn -- Find a connection in the linked list of connections.
4811592Srgrimes**
4821592Srgrimes**	We use the RMP (Ethernet) address as the basis for determining
4831592Srgrimes**	if this is the same connection.  According to the Remote Maint
4841592Srgrimes**	Protocol, we can only have one connection with any machine.
4851592Srgrimes**
4861592Srgrimes**	Parameters:
4871592Srgrimes**		rconn - connection to be found.
4881592Srgrimes**
4891592Srgrimes**	Returns:
4901592Srgrimes**		Matching connection from linked list or NULL if not found.
4911592Srgrimes**
4921592Srgrimes**	Side Effects:
4931592Srgrimes**		None.
4941592Srgrimes**
4951592Srgrimes**	Warnings:
4961592Srgrimes**		- This routine must be called with SIGHUP blocked.
4971592Srgrimes*/
4981592SrgrimesRMPCONN *
49990377SimpFindConn(RMPCONN *rconn)
5001592Srgrimes{
50127079Ssteve	RMPCONN *rtmp;
5021592Srgrimes
5031592Srgrimes	for (rtmp = RmpConns; rtmp != NULL; rtmp = rtmp->next)
5041592Srgrimes		if (bcmp((char *)&rconn->rmp.hp_hdr.saddr[0],
5051592Srgrimes		         (char *)&rtmp->rmp.hp_hdr.saddr[0], RMP_ADDRLEN) == 0)
5061592Srgrimes			break;
5071592Srgrimes
5081592Srgrimes	return(rtmp);
5091592Srgrimes}
5101592Srgrimes
5111592Srgrimes/*
5121592Srgrimes**  RemoveConn -- Remove a connection from the linked list of connections.
5131592Srgrimes**
5141592Srgrimes**	Parameters:
5151592Srgrimes**		rconn - connection to be removed.
5161592Srgrimes**
5171592Srgrimes**	Returns:
5181592Srgrimes**		Nothing.
5191592Srgrimes**
5201592Srgrimes**	Side Effects:
5211592Srgrimes**		- If found, an RMPCONN will cease to exist and it will
5221592Srgrimes**		  be removed from the linked list.
5231592Srgrimes**
5241592Srgrimes**	Warnings:
5251592Srgrimes**		- This routine must be called with SIGHUP blocked.
5261592Srgrimes*/
5271592Srgrimesvoid
52890377SimpRemoveConn(RMPCONN *rconn)
5291592Srgrimes{
53027079Ssteve	RMPCONN *thisrconn, *lastrconn;
5311592Srgrimes
5321592Srgrimes	if (RmpConns == rconn) {		/* easy case */
5331592Srgrimes		RmpConns = RmpConns->next;
5341592Srgrimes		FreeConn(rconn);
5351592Srgrimes	} else {				/* must traverse linked list */
5361592Srgrimes		lastrconn = RmpConns;			/* set back ptr */
5371592Srgrimes		thisrconn = lastrconn->next;		/* set current ptr */
5381592Srgrimes		while (thisrconn != NULL) {
5391592Srgrimes			if (rconn == thisrconn) {		/* found it */
5401592Srgrimes				lastrconn->next = thisrconn->next;
5411592Srgrimes				FreeConn(thisrconn);
5421592Srgrimes				break;
5431592Srgrimes			}
5441592Srgrimes			lastrconn = thisrconn;
5451592Srgrimes			thisrconn = thisrconn->next;
5461592Srgrimes		}
5471592Srgrimes	}
5481592Srgrimes}
549