utils.c revision 90377
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: head/libexec/rbootd/utils.c 90377 2002-02-07 23:57:01Z imp $";
531592Srgrimes#endif /* not lint */
541592Srgrimes
551592Srgrimes#include <sys/param.h>
5627077Ssteve#include <sys/time.h>
571592Srgrimes
581592Srgrimes#include <fcntl.h>
591592Srgrimes#include <signal.h>
601592Srgrimes#include <stdio.h>
611592Srgrimes#include <stdlib.h>
621592Srgrimes#include <string.h>
631592Srgrimes#include <syslog.h>
641592Srgrimes#include <time.h>
651592Srgrimes#include <unistd.h>
661592Srgrimes#include "defs.h"
671592Srgrimes
681592Srgrimes/*
691592Srgrimes**  DispPkt -- Display the contents of an RMPCONN packet.
701592Srgrimes**
711592Srgrimes**	Parameters:
721592Srgrimes**		rconn - packet to be displayed.
731592Srgrimes**		direct - direction packet is going (DIR_*).
741592Srgrimes**
751592Srgrimes**	Returns:
761592Srgrimes**		Nothing.
771592Srgrimes**
781592Srgrimes**	Side Effects:
791592Srgrimes**		None.
801592Srgrimes*/
811592Srgrimesvoid
8290377SimpDispPkt(RMPCONN *rconn, int direct)
831592Srgrimes{
8469252Skris	static const char BootFmt[] = "\t\tRetCode:%u SeqNo:%lx SessID:%x Vers:%u";
8569252Skris	static const char ReadFmt[] = "\t\tRetCode:%u Offset:%lx SessID:%x\n";
861592Srgrimes
871592Srgrimes	struct tm *tmp;
8827079Ssteve	struct rmp_packet *rmp;
891592Srgrimes	int i, omask;
9027074Ssteve	u_int32_t t;
911592Srgrimes
921592Srgrimes	/*
931592Srgrimes	 *  Since we will be working with RmpConns as well as DbgFp, we
941592Srgrimes	 *  must block signals that can affect either.
951592Srgrimes	 */
961592Srgrimes	omask = sigblock(sigmask(SIGHUP)|sigmask(SIGUSR1)|sigmask(SIGUSR2));
971592Srgrimes
981592Srgrimes	if (DbgFp == NULL) {			/* sanity */
991592Srgrimes		(void) sigsetmask(omask);
1001592Srgrimes		return;
1011592Srgrimes	}
1021592Srgrimes
1031592Srgrimes	/* display direction packet is going using '>>>' or '<<<' */
1041592Srgrimes	fputs((direct==DIR_RCVD)?"<<< ":(direct==DIR_SENT)?">>> ":"", DbgFp);
1051592Srgrimes
1061592Srgrimes	/* display packet timestamp */
1071592Srgrimes	tmp = localtime((time_t *)&rconn->tstamp.tv_sec);
1081592Srgrimes	fprintf(DbgFp, "%02d:%02d:%02d.%06ld   ", tmp->tm_hour, tmp->tm_min,
1091592Srgrimes	        tmp->tm_sec, rconn->tstamp.tv_usec);
1101592Srgrimes
1111592Srgrimes	/* display src or dst addr and information about network interface */
1121592Srgrimes	fprintf(DbgFp, "Addr: %s   Intf: %s\n", EnetStr(rconn), IntfName);
1131592Srgrimes
1141592Srgrimes	rmp = &rconn->rmp;
1151592Srgrimes
1161592Srgrimes	/* display IEEE 802.2 Logical Link Control header */
1171592Srgrimes	(void) fprintf(DbgFp, "\t802.2 LLC: DSAP:%x SSAP:%x CTRL:%x\n",
11827074Ssteve               rmp->hp_llc.dsap, rmp->hp_llc.ssap, ntohs(rmp->hp_llc.cntrl));
1191592Srgrimes
1201592Srgrimes	/* display HP extensions to 802.2 Logical Link Control header */
1211592Srgrimes	(void) fprintf(DbgFp, "\tHP Ext:    DXSAP:%x SXSAP:%x\n",
12227074Ssteve	               ntohs(rmp->hp_llc.dxsap), ntohs(rmp->hp_llc.sxsap));
1231592Srgrimes
1241592Srgrimes	/*
1251592Srgrimes	 *  Display information about RMP packet using type field to
1261592Srgrimes	 *  determine what kind of packet this is.
1271592Srgrimes	 */
1281592Srgrimes	switch(rmp->r_type) {
1291592Srgrimes		case RMP_BOOT_REQ:		/* boot request */
1301592Srgrimes			(void) fprintf(DbgFp, "\tBoot Request:");
1311592Srgrimes			GETWORD(rmp->r_brq.rmp_seqno, t);
13227074Ssteve			if (ntohs(rmp->r_brq.rmp_session) == RMP_PROBESID) {
1331592Srgrimes				if (WORDZE(rmp->r_brq.rmp_seqno))
1341592Srgrimes					fputs(" (Send Server ID)", DbgFp);
1351592Srgrimes				else
1361592Srgrimes					fprintf(DbgFp," (Send Filename #%u)",t);
1371592Srgrimes			}
1381592Srgrimes			(void) fputc('\n', DbgFp);
1391592Srgrimes			(void) fprintf(DbgFp, BootFmt, rmp->r_brq.rmp_retcode,
14027074Ssteve			        t, ntohs(rmp->r_brq.rmp_session),
14127074Ssteve			        ntohs(rmp->r_brq.rmp_version));
1421592Srgrimes			(void) fprintf(DbgFp, "\n\t\tMachine Type: ");
1431592Srgrimes			for (i = 0; i < RMP_MACHLEN; i++)
1441592Srgrimes				(void) fputc(rmp->r_brq.rmp_machtype[i], DbgFp);
1451592Srgrimes			DspFlnm(rmp->r_brq.rmp_flnmsize, &rmp->r_brq.rmp_flnm);
1461592Srgrimes			break;
1471592Srgrimes		case RMP_BOOT_REPL:		/* boot reply */
1481592Srgrimes			fprintf(DbgFp, "\tBoot Reply:\n");
1491592Srgrimes			GETWORD(rmp->r_brpl.rmp_seqno, t);
1501592Srgrimes			(void) fprintf(DbgFp, BootFmt, rmp->r_brpl.rmp_retcode,
15127074Ssteve			        t, ntohs(rmp->r_brpl.rmp_session),
15227074Ssteve			        ntohs(rmp->r_brpl.rmp_version));
1531592Srgrimes			DspFlnm(rmp->r_brpl.rmp_flnmsize,&rmp->r_brpl.rmp_flnm);
1541592Srgrimes			break;
1551592Srgrimes		case RMP_READ_REQ:		/* read request */
1561592Srgrimes			(void) fprintf(DbgFp, "\tRead Request:\n");
1571592Srgrimes			GETWORD(rmp->r_rrq.rmp_offset, t);
1581592Srgrimes			(void) fprintf(DbgFp, ReadFmt, rmp->r_rrq.rmp_retcode,
15927074Ssteve			        t, ntohs(rmp->r_rrq.rmp_session));
1601592Srgrimes			(void) fprintf(DbgFp, "\t\tNoOfBytes: %u\n",
16127074Ssteve			        ntohs(rmp->r_rrq.rmp_size));
1621592Srgrimes			break;
1631592Srgrimes		case RMP_READ_REPL:		/* read reply */
1641592Srgrimes			(void) fprintf(DbgFp, "\tRead Reply:\n");
1651592Srgrimes			GETWORD(rmp->r_rrpl.rmp_offset, t);
1661592Srgrimes			(void) fprintf(DbgFp, ReadFmt, rmp->r_rrpl.rmp_retcode,
16727074Ssteve			        t, ntohs(rmp->r_rrpl.rmp_session));
1681592Srgrimes			(void) fprintf(DbgFp, "\t\tNoOfBytesSent: %d\n",
1691592Srgrimes			        rconn->rmplen - RMPREADSIZE(0));
1701592Srgrimes			break;
1711592Srgrimes		case RMP_BOOT_DONE:		/* boot complete */
1721592Srgrimes			(void) fprintf(DbgFp, "\tBoot Complete:\n");
1731592Srgrimes			(void) fprintf(DbgFp, "\t\tRetCode:%u SessID:%x\n",
1741592Srgrimes			        rmp->r_done.rmp_retcode,
17527074Ssteve			        ntohs(rmp->r_done.rmp_session));
1761592Srgrimes			break;
1771592Srgrimes		default:			/* ??? */
1781592Srgrimes			(void) fprintf(DbgFp, "\tUnknown Type:(%d)\n",
1791592Srgrimes				rmp->r_type);
1801592Srgrimes	}
1811592Srgrimes	(void) fputc('\n', DbgFp);
1821592Srgrimes	(void) fflush(DbgFp);
1831592Srgrimes
1841592Srgrimes	(void) sigsetmask(omask);		/* reset old signal mask */
1851592Srgrimes}
1861592Srgrimes
1871592Srgrimes
1881592Srgrimes/*
1891592Srgrimes**  GetEtherAddr -- convert an RMP (Ethernet) address into a string.
1901592Srgrimes**
1911592Srgrimes**	An RMP BOOT packet has been received.  Look at the type field
1921592Srgrimes**	and process Boot Requests, Read Requests, and Boot Complete
1931592Srgrimes**	packets.  Any other type will be dropped with a warning msg.
1941592Srgrimes**
1951592Srgrimes**	Parameters:
1961592Srgrimes**		addr - array of RMP_ADDRLEN bytes.
1971592Srgrimes**
1981592Srgrimes**	Returns:
1991592Srgrimes**		Pointer to static string representation of `addr'.
2001592Srgrimes**
2011592Srgrimes**	Side Effects:
2021592Srgrimes**		None.
2031592Srgrimes**
2041592Srgrimes**	Warnings:
2051592Srgrimes**		- The return value points to a static buffer; it must
2061592Srgrimes**		  be copied if it's to be saved.
2071592Srgrimes*/
2081592Srgrimeschar *
20990377SimpGetEtherAddr(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
24990377SimpDspFlnm(u_int size, char *flnm)
2501592Srgrimes{
25127079Ssteve	int i;
2521592Srgrimes
25327074Ssteve	(void) fprintf(DbgFp, "\n\t\tFile Name (%u): <", size);
2541592Srgrimes	for (i = 0; i < size; i++)
2551592Srgrimes		(void) fputc(*flnm++, DbgFp);
2561592Srgrimes	(void) fputs(">\n", DbgFp);
2571592Srgrimes}
2581592Srgrimes
2591592Srgrimes
2601592Srgrimes/*
2611592Srgrimes**  NewClient -- allocate memory for a new CLIENT.
2621592Srgrimes**
2631592Srgrimes**	Parameters:
2641592Srgrimes**		addr - RMP (Ethernet) address of new client.
2651592Srgrimes**
2661592Srgrimes**	Returns:
2671592Srgrimes**		Ptr to new CLIENT or NULL if we ran out of memory.
2681592Srgrimes**
2691592Srgrimes**	Side Effects:
2701592Srgrimes**		- Memory will be malloc'd for the new CLIENT.
2711592Srgrimes**		- If malloc() fails, a log message will be generated.
2721592Srgrimes*/
2731592SrgrimesCLIENT *
27490377SimpNewClient(u_int8_t *addr)
2751592Srgrimes{
2761592Srgrimes	CLIENT *ctmp;
2771592Srgrimes
2781592Srgrimes	if ((ctmp = (CLIENT *) malloc(sizeof(CLIENT))) == NULL) {
2791592Srgrimes		syslog(LOG_ERR, "NewClient: out of memory (%s)",
2801592Srgrimes		       GetEtherAddr(addr));
2811592Srgrimes		return(NULL);
2821592Srgrimes	}
2831592Srgrimes
28427079Ssteve	memset(ctmp, 0, sizeof(CLIENT));
28527079Ssteve	memmove(&ctmp->addr[0], addr, RMP_ADDRLEN);
2861592Srgrimes	return(ctmp);
2871592Srgrimes}
2881592Srgrimes
2891592Srgrimes/*
2901592Srgrimes**  FreeClient -- free linked list of Clients.
2911592Srgrimes**
2921592Srgrimes**	Parameters:
2931592Srgrimes**		None.
2941592Srgrimes**
2951592Srgrimes**	Returns:
2961592Srgrimes**		Nothing.
2971592Srgrimes**
2981592Srgrimes**	Side Effects:
2991592Srgrimes**		- All malloc'd memory associated with the linked list of
3001592Srgrimes**		  CLIENTS will be free'd; `Clients' will be set to NULL.
3011592Srgrimes**
3021592Srgrimes**	Warnings:
3031592Srgrimes**		- This routine must be called with SIGHUP blocked.
3041592Srgrimes*/
3051592Srgrimesvoid
30690377SimpFreeClients(void)
3071592Srgrimes{
30827079Ssteve	CLIENT *ctmp;
3091592Srgrimes
3101592Srgrimes	while (Clients != NULL) {
3111592Srgrimes		ctmp = Clients;
3121592Srgrimes		Clients = Clients->next;
3131592Srgrimes		FreeClient(ctmp);
3141592Srgrimes	}
3151592Srgrimes}
3161592Srgrimes
3171592Srgrimes/*
3181592Srgrimes**  NewStr -- allocate memory for a character array.
3191592Srgrimes**
3201592Srgrimes**	Parameters:
3211592Srgrimes**		str - null terminated character array.
3221592Srgrimes**
3231592Srgrimes**	Returns:
3241592Srgrimes**		Ptr to new character array or NULL if we ran out of memory.
3251592Srgrimes**
3261592Srgrimes**	Side Effects:
3271592Srgrimes**		- Memory will be malloc'd for the new character array.
3281592Srgrimes**		- If malloc() fails, a log message will be generated.
3291592Srgrimes*/
3301592Srgrimeschar *
33190377SimpNewStr(char *str)
3321592Srgrimes{
3331592Srgrimes	char *stmp;
3341592Srgrimes
3351592Srgrimes	if ((stmp = (char *)malloc((unsigned) (strlen(str)+1))) == NULL) {
3361592Srgrimes		syslog(LOG_ERR, "NewStr: out of memory (%s)", str);
3371592Srgrimes		return(NULL);
3381592Srgrimes	}
3391592Srgrimes
3401592Srgrimes	(void) strcpy(stmp, str);
3411592Srgrimes	return(stmp);
3421592Srgrimes}
3431592Srgrimes
3441592Srgrimes/*
3451592Srgrimes**  To save time, NewConn and FreeConn maintain a cache of one RMPCONN
3461592Srgrimes**  in `LastFree' (defined below).
3471592Srgrimes*/
3481592Srgrimes
3491592Srgrimesstatic RMPCONN *LastFree = NULL;
3501592Srgrimes
3511592Srgrimes/*
3521592Srgrimes**  NewConn -- allocate memory for a new RMPCONN connection.
3531592Srgrimes**
3541592Srgrimes**	Parameters:
3551592Srgrimes**		rconn - initialization template for new connection.
3561592Srgrimes**
3571592Srgrimes**	Returns:
3581592Srgrimes**		Ptr to new RMPCONN or NULL if we ran out of memory.
3591592Srgrimes**
3601592Srgrimes**	Side Effects:
3611592Srgrimes**		- Memory may be malloc'd for the new RMPCONN (if not cached).
3621592Srgrimes**		- If malloc() fails, a log message will be generated.
3631592Srgrimes*/
3641592SrgrimesRMPCONN *
36590377SimpNewConn(RMPCONN *rconn)
3661592Srgrimes{
3671592Srgrimes	RMPCONN *rtmp;
3681592Srgrimes
3691592Srgrimes	if (LastFree == NULL) {		/* nothing cached; make a new one */
3701592Srgrimes		if ((rtmp = (RMPCONN *) malloc(sizeof(RMPCONN))) == NULL) {
3711592Srgrimes			syslog(LOG_ERR, "NewConn: out of memory (%s)",
3721592Srgrimes			       EnetStr(rconn));
3731592Srgrimes			return(NULL);
3741592Srgrimes		}
3751592Srgrimes	} else {			/* use the cached RMPCONN */
3761592Srgrimes		rtmp = LastFree;
3771592Srgrimes		LastFree = NULL;
3781592Srgrimes	}
3791592Srgrimes
3801592Srgrimes	/*
3811592Srgrimes	 *  Copy template into `rtmp', init file descriptor to `-1' and
3821592Srgrimes	 *  set ptr to next elem NULL.
3831592Srgrimes	 */
38427079Ssteve	memmove((char *)rtmp, (char *)rconn, sizeof(RMPCONN));
3851592Srgrimes	rtmp->bootfd = -1;
3861592Srgrimes	rtmp->next = NULL;
3871592Srgrimes
3881592Srgrimes	return(rtmp);
3891592Srgrimes}
3901592Srgrimes
3911592Srgrimes/*
3921592Srgrimes**  FreeConn -- Free memory associated with an RMPCONN connection.
3931592Srgrimes**
3941592Srgrimes**	Parameters:
3951592Srgrimes**		rtmp - ptr to RMPCONN to be free'd.
3961592Srgrimes**
3971592Srgrimes**	Returns:
3981592Srgrimes**		Nothing.
3991592Srgrimes**
4001592Srgrimes**	Side Effects:
4011592Srgrimes**		- Memory associated with `rtmp' may be free'd (or cached).
4021592Srgrimes**		- File desc associated with `rtmp->bootfd' will be closed.
4031592Srgrimes*/
4041592Srgrimesvoid
40590377SimpFreeConn(RMPCONN *rtmp)
4061592Srgrimes{
4071592Srgrimes	/*
4081592Srgrimes	 *  If the file descriptor is in use, close the file.
4091592Srgrimes	 */
4101592Srgrimes	if (rtmp->bootfd >= 0) {
4111592Srgrimes		(void) close(rtmp->bootfd);
4121592Srgrimes		rtmp->bootfd = -1;
4131592Srgrimes	}
4141592Srgrimes
4151592Srgrimes	if (LastFree == NULL)		/* cache for next time */
4161592Srgrimes		rtmp = LastFree;
4171592Srgrimes	else				/* already one cached; free this one */
4181592Srgrimes		free((char *)rtmp);
4191592Srgrimes}
4201592Srgrimes
4211592Srgrimes/*
4221592Srgrimes**  FreeConns -- free linked list of RMPCONN connections.
4231592Srgrimes**
4241592Srgrimes**	Parameters:
4251592Srgrimes**		None.
4261592Srgrimes**
4271592Srgrimes**	Returns:
4281592Srgrimes**		Nothing.
4291592Srgrimes**
4301592Srgrimes**	Side Effects:
4311592Srgrimes**		- All malloc'd memory associated with the linked list of
4321592Srgrimes**		  connections will be free'd; `RmpConns' will be set to NULL.
4331592Srgrimes**		- If LastFree is != NULL, it too will be free'd & NULL'd.
4341592Srgrimes**
4351592Srgrimes**	Warnings:
4361592Srgrimes**		- This routine must be called with SIGHUP blocked.
4371592Srgrimes*/
4381592Srgrimesvoid
43990377SimpFreeConns(void)
4401592Srgrimes{
44127079Ssteve	RMPCONN *rtmp;
4421592Srgrimes
4431592Srgrimes	while (RmpConns != NULL) {
4441592Srgrimes		rtmp = RmpConns;
4451592Srgrimes		RmpConns = RmpConns->next;
4461592Srgrimes		FreeConn(rtmp);
4471592Srgrimes	}
4481592Srgrimes
4491592Srgrimes	if (LastFree != NULL) {
4501592Srgrimes		free((char *)LastFree);
4511592Srgrimes		LastFree = NULL;
4521592Srgrimes	}
4531592Srgrimes}
4541592Srgrimes
4551592Srgrimes/*
4561592Srgrimes**  AddConn -- Add a connection to the linked list of connections.
4571592Srgrimes**
4581592Srgrimes**	Parameters:
4591592Srgrimes**		rconn - connection to be added.
4601592Srgrimes**
4611592Srgrimes**	Returns:
4621592Srgrimes**		Nothing.
4631592Srgrimes**
4641592Srgrimes**	Side Effects:
4651592Srgrimes**		- RmpConn will point to new connection.
4661592Srgrimes**
4671592Srgrimes**	Warnings:
4681592Srgrimes**		- This routine must be called with SIGHUP blocked.
4691592Srgrimes*/
4701592Srgrimesvoid
47190377SimpAddConn(RMPCONN *rconn)
4721592Srgrimes{
4731592Srgrimes	if (RmpConns != NULL)
4741592Srgrimes		rconn->next = RmpConns;
4751592Srgrimes	RmpConns = rconn;
4761592Srgrimes}
4771592Srgrimes
4781592Srgrimes/*
4791592Srgrimes**  FindConn -- Find a connection in the linked list of connections.
4801592Srgrimes**
4811592Srgrimes**	We use the RMP (Ethernet) address as the basis for determining
4821592Srgrimes**	if this is the same connection.  According to the Remote Maint
4831592Srgrimes**	Protocol, we can only have one connection with any machine.
4841592Srgrimes**
4851592Srgrimes**	Parameters:
4861592Srgrimes**		rconn - connection to be found.
4871592Srgrimes**
4881592Srgrimes**	Returns:
4891592Srgrimes**		Matching connection from linked list or NULL if not found.
4901592Srgrimes**
4911592Srgrimes**	Side Effects:
4921592Srgrimes**		None.
4931592Srgrimes**
4941592Srgrimes**	Warnings:
4951592Srgrimes**		- This routine must be called with SIGHUP blocked.
4961592Srgrimes*/
4971592SrgrimesRMPCONN *
49890377SimpFindConn(RMPCONN *rconn)
4991592Srgrimes{
50027079Ssteve	RMPCONN *rtmp;
5011592Srgrimes
5021592Srgrimes	for (rtmp = RmpConns; rtmp != NULL; rtmp = rtmp->next)
5031592Srgrimes		if (bcmp((char *)&rconn->rmp.hp_hdr.saddr[0],
5041592Srgrimes		         (char *)&rtmp->rmp.hp_hdr.saddr[0], RMP_ADDRLEN) == 0)
5051592Srgrimes			break;
5061592Srgrimes
5071592Srgrimes	return(rtmp);
5081592Srgrimes}
5091592Srgrimes
5101592Srgrimes/*
5111592Srgrimes**  RemoveConn -- Remove a connection from the linked list of connections.
5121592Srgrimes**
5131592Srgrimes**	Parameters:
5141592Srgrimes**		rconn - connection to be removed.
5151592Srgrimes**
5161592Srgrimes**	Returns:
5171592Srgrimes**		Nothing.
5181592Srgrimes**
5191592Srgrimes**	Side Effects:
5201592Srgrimes**		- If found, an RMPCONN will cease to exist and it will
5211592Srgrimes**		  be removed from the linked list.
5221592Srgrimes**
5231592Srgrimes**	Warnings:
5241592Srgrimes**		- This routine must be called with SIGHUP blocked.
5251592Srgrimes*/
5261592Srgrimesvoid
52790377SimpRemoveConn(RMPCONN *rconn)
5281592Srgrimes{
52927079Ssteve	RMPCONN *thisrconn, *lastrconn;
5301592Srgrimes
5311592Srgrimes	if (RmpConns == rconn) {		/* easy case */
5321592Srgrimes		RmpConns = RmpConns->next;
5331592Srgrimes		FreeConn(rconn);
5341592Srgrimes	} else {				/* must traverse linked list */
5351592Srgrimes		lastrconn = RmpConns;			/* set back ptr */
5361592Srgrimes		thisrconn = lastrconn->next;		/* set current ptr */
5371592Srgrimes		while (thisrconn != NULL) {
5381592Srgrimes			if (rconn == thisrconn) {		/* found it */
5391592Srgrimes				lastrconn->next = thisrconn->next;
5401592Srgrimes				FreeConn(thisrconn);
5411592Srgrimes				break;
5421592Srgrimes			}
5431592Srgrimes			lastrconn = thisrconn;
5441592Srgrimes			thisrconn = thisrconn->next;
5451592Srgrimes		}
5461592Srgrimes	}
5471592Srgrimes}
548