Home | History | Annotate | Line # | Download | only in rbootd
utils.c revision 1.5.2.1
      1  1.5.2.1  thorpej /*	$NetBSD: utils.c,v 1.5.2.1 1995/11/14 08:45:46 thorpej Exp $	*/
      2      1.3  thorpej 
      3      1.1   brezak /*
      4      1.1   brezak  * Copyright (c) 1988, 1992 The University of Utah and the Center
      5      1.1   brezak  *	for Software Science (CSS).
      6      1.1   brezak  * Copyright (c) 1992, 1993
      7      1.1   brezak  *	The Regents of the University of California.  All rights reserved.
      8      1.1   brezak  *
      9      1.1   brezak  * This code is derived from software contributed to Berkeley by
     10      1.1   brezak  * the Center for Software Science of the University of Utah Computer
     11      1.1   brezak  * Science Department.  CSS requests users of this software to return
     12      1.1   brezak  * to css-dist (at) cs.utah.edu any improvements that they make and grant
     13      1.1   brezak  * CSS redistribution rights.
     14      1.1   brezak  *
     15      1.1   brezak  * Redistribution and use in source and binary forms, with or without
     16      1.1   brezak  * modification, are permitted provided that the following conditions
     17      1.1   brezak  * are met:
     18      1.1   brezak  * 1. Redistributions of source code must retain the above copyright
     19      1.1   brezak  *    notice, this list of conditions and the following disclaimer.
     20      1.1   brezak  * 2. Redistributions in binary form must reproduce the above copyright
     21      1.1   brezak  *    notice, this list of conditions and the following disclaimer in the
     22      1.1   brezak  *    documentation and/or other materials provided with the distribution.
     23      1.1   brezak  * 3. All advertising materials mentioning features or use of this software
     24      1.1   brezak  *    must display the following acknowledgement:
     25      1.1   brezak  *	This product includes software developed by the University of
     26      1.1   brezak  *	California, Berkeley and its contributors.
     27      1.1   brezak  * 4. Neither the name of the University nor the names of its contributors
     28      1.1   brezak  *    may be used to endorse or promote products derived from this software
     29      1.1   brezak  *    without specific prior written permission.
     30      1.1   brezak  *
     31      1.1   brezak  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     32      1.1   brezak  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     33      1.1   brezak  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     34      1.1   brezak  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     35      1.1   brezak  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     36      1.1   brezak  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     37      1.1   brezak  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     38      1.1   brezak  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     39      1.1   brezak  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     40      1.1   brezak  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     41      1.1   brezak  * SUCH DAMAGE.
     42      1.1   brezak  *
     43      1.2   brezak  *	from: @(#)utils.c	8.1 (Berkeley) 6/4/93
     44      1.1   brezak  *
     45      1.2   brezak  * From: Utah Hdr: utils.c 3.1 92/07/06
     46      1.1   brezak  * Author: Jeff Forys, University of Utah CSS
     47      1.1   brezak  */
     48      1.1   brezak 
     49      1.1   brezak #ifndef lint
     50      1.2   brezak /*static char sccsid[] = "@(#)utils.c	8.1 (Berkeley) 6/4/93";*/
     51  1.5.2.1  thorpej static char rcsid[] = "$NetBSD: utils.c,v 1.5.2.1 1995/11/14 08:45:46 thorpej Exp $";
     52      1.1   brezak #endif /* not lint */
     53      1.1   brezak 
     54      1.1   brezak #include <sys/param.h>
     55      1.1   brezak 
     56      1.1   brezak #include <fcntl.h>
     57      1.1   brezak #include <signal.h>
     58      1.1   brezak #include <stdio.h>
     59      1.1   brezak #include <stdlib.h>
     60      1.1   brezak #include <string.h>
     61      1.1   brezak #include <syslog.h>
     62      1.1   brezak #include <time.h>
     63      1.1   brezak #include <unistd.h>
     64      1.1   brezak #include "defs.h"
     65      1.1   brezak 
     66      1.1   brezak /*
     67      1.1   brezak **  DispPkt -- Display the contents of an RMPCONN packet.
     68      1.1   brezak **
     69      1.1   brezak **	Parameters:
     70      1.1   brezak **		rconn - packet to be displayed.
     71      1.1   brezak **		direct - direction packet is going (DIR_*).
     72      1.1   brezak **
     73      1.1   brezak **	Returns:
     74      1.1   brezak **		Nothing.
     75      1.1   brezak **
     76      1.1   brezak **	Side Effects:
     77      1.1   brezak **		None.
     78      1.1   brezak */
     79      1.1   brezak void
     80      1.1   brezak DispPkt(rconn, direct)
     81      1.1   brezak 	RMPCONN *rconn;
     82      1.1   brezak 	int direct;
     83      1.1   brezak {
     84      1.1   brezak 	static char BootFmt[] = "\t\tRetCode:%u SeqNo:%lx SessID:%x Vers:%u";
     85      1.1   brezak 	static char ReadFmt[] = "\t\tRetCode:%u Offset:%lx SessID:%x\n";
     86      1.1   brezak 
     87      1.1   brezak 	struct tm *tmp;
     88      1.1   brezak 	register struct rmp_packet *rmp;
     89      1.1   brezak 	int i, omask;
     90      1.5  thorpej 	u_int32_t t;
     91      1.1   brezak 
     92      1.1   brezak 	/*
     93      1.1   brezak 	 *  Since we will be working with RmpConns as well as DbgFp, we
     94      1.1   brezak 	 *  must block signals that can affect either.
     95      1.1   brezak 	 */
     96      1.1   brezak 	omask = sigblock(sigmask(SIGHUP)|sigmask(SIGUSR1)|sigmask(SIGUSR2));
     97      1.1   brezak 
     98      1.1   brezak 	if (DbgFp == NULL) {			/* sanity */
     99      1.1   brezak 		(void) sigsetmask(omask);
    100      1.1   brezak 		return;
    101      1.1   brezak 	}
    102      1.1   brezak 
    103      1.1   brezak 	/* display direction packet is going using '>>>' or '<<<' */
    104      1.1   brezak 	fputs((direct==DIR_RCVD)?"<<< ":(direct==DIR_SENT)?">>> ":"", DbgFp);
    105      1.1   brezak 
    106      1.1   brezak 	/* display packet timestamp */
    107      1.1   brezak 	tmp = localtime((time_t *)&rconn->tstamp.tv_sec);
    108      1.1   brezak 	fprintf(DbgFp, "%02d:%02d:%02d.%06ld   ", tmp->tm_hour, tmp->tm_min,
    109      1.1   brezak 	        tmp->tm_sec, rconn->tstamp.tv_usec);
    110      1.1   brezak 
    111      1.1   brezak 	/* display src or dst addr and information about network interface */
    112      1.1   brezak 	fprintf(DbgFp, "Addr: %s   Intf: %s\n", EnetStr(rconn), IntfName);
    113      1.1   brezak 
    114      1.1   brezak 	rmp = &rconn->rmp;
    115      1.1   brezak 
    116      1.1   brezak 	/* display IEEE 802.2 Logical Link Control header */
    117      1.1   brezak 	(void) fprintf(DbgFp, "\t802.2 LLC: DSAP:%x SSAP:%x CTRL:%x\n",
    118      1.4  thorpej                rmp->hp_llc.dsap, rmp->hp_llc.ssap, ntohs(rmp->hp_llc.cntrl));
    119      1.1   brezak 
    120      1.1   brezak 	/* display HP extensions to 802.2 Logical Link Control header */
    121      1.1   brezak 	(void) fprintf(DbgFp, "\tHP Ext:    DXSAP:%x SXSAP:%x\n",
    122      1.4  thorpej 	               ntohs(rmp->hp_llc.dxsap), ntohs(rmp->hp_llc.sxsap));
    123      1.1   brezak 
    124      1.1   brezak 	/*
    125      1.1   brezak 	 *  Display information about RMP packet using type field to
    126      1.1   brezak 	 *  determine what kind of packet this is.
    127      1.1   brezak 	 */
    128      1.1   brezak 	switch(rmp->r_type) {
    129      1.1   brezak 		case RMP_BOOT_REQ:		/* boot request */
    130      1.1   brezak 			(void) fprintf(DbgFp, "\tBoot Request:");
    131      1.1   brezak 			GETWORD(rmp->r_brq.rmp_seqno, t);
    132      1.4  thorpej 			if (ntohs(rmp->r_brq.rmp_session) == RMP_PROBESID) {
    133      1.1   brezak 				if (WORDZE(rmp->r_brq.rmp_seqno))
    134      1.1   brezak 					fputs(" (Send Server ID)", DbgFp);
    135      1.1   brezak 				else
    136      1.1   brezak 					fprintf(DbgFp," (Send Filename #%u)",t);
    137      1.1   brezak 			}
    138      1.1   brezak 			(void) fputc('\n', DbgFp);
    139      1.1   brezak 			(void) fprintf(DbgFp, BootFmt, rmp->r_brq.rmp_retcode,
    140      1.4  thorpej 			        t, ntohs(rmp->r_brq.rmp_session),
    141      1.4  thorpej 			        ntohs(rmp->r_brq.rmp_version));
    142      1.1   brezak 			(void) fprintf(DbgFp, "\n\t\tMachine Type: ");
    143      1.1   brezak 			for (i = 0; i < RMP_MACHLEN; i++)
    144      1.1   brezak 				(void) fputc(rmp->r_brq.rmp_machtype[i], DbgFp);
    145      1.1   brezak 			DspFlnm(rmp->r_brq.rmp_flnmsize, &rmp->r_brq.rmp_flnm);
    146      1.1   brezak 			break;
    147      1.1   brezak 		case RMP_BOOT_REPL:		/* boot reply */
    148      1.1   brezak 			fprintf(DbgFp, "\tBoot Reply:\n");
    149      1.1   brezak 			GETWORD(rmp->r_brpl.rmp_seqno, t);
    150      1.1   brezak 			(void) fprintf(DbgFp, BootFmt, rmp->r_brpl.rmp_retcode,
    151      1.4  thorpej 			        t, ntohs(rmp->r_brpl.rmp_session),
    152      1.4  thorpej 			        ntohs(rmp->r_brpl.rmp_version));
    153      1.1   brezak 			DspFlnm(rmp->r_brpl.rmp_flnmsize,&rmp->r_brpl.rmp_flnm);
    154      1.1   brezak 			break;
    155      1.1   brezak 		case RMP_READ_REQ:		/* read request */
    156      1.1   brezak 			(void) fprintf(DbgFp, "\tRead Request:\n");
    157      1.1   brezak 			GETWORD(rmp->r_rrq.rmp_offset, t);
    158      1.1   brezak 			(void) fprintf(DbgFp, ReadFmt, rmp->r_rrq.rmp_retcode,
    159      1.4  thorpej 			        t, ntohs(rmp->r_rrq.rmp_session));
    160      1.1   brezak 			(void) fprintf(DbgFp, "\t\tNoOfBytes: %u\n",
    161      1.4  thorpej 			        ntohs(rmp->r_rrq.rmp_size));
    162      1.1   brezak 			break;
    163      1.1   brezak 		case RMP_READ_REPL:		/* read reply */
    164      1.1   brezak 			(void) fprintf(DbgFp, "\tRead Reply:\n");
    165      1.1   brezak 			GETWORD(rmp->r_rrpl.rmp_offset, t);
    166      1.1   brezak 			(void) fprintf(DbgFp, ReadFmt, rmp->r_rrpl.rmp_retcode,
    167      1.4  thorpej 			        t, ntohs(rmp->r_rrpl.rmp_session));
    168      1.1   brezak 			(void) fprintf(DbgFp, "\t\tNoOfBytesSent: %d\n",
    169  1.5.2.1  thorpej 			        rconn->rmplen - RMPREADSIZE(0));
    170      1.1   brezak 			break;
    171      1.1   brezak 		case RMP_BOOT_DONE:		/* boot complete */
    172      1.1   brezak 			(void) fprintf(DbgFp, "\tBoot Complete:\n");
    173      1.1   brezak 			(void) fprintf(DbgFp, "\t\tRetCode:%u SessID:%x\n",
    174      1.1   brezak 			        rmp->r_done.rmp_retcode,
    175      1.4  thorpej 			        ntohs(rmp->r_done.rmp_session));
    176      1.1   brezak 			break;
    177      1.1   brezak 		default:			/* ??? */
    178      1.1   brezak 			(void) fprintf(DbgFp, "\tUnknown Type:(%d)\n",
    179      1.1   brezak 				rmp->r_type);
    180      1.1   brezak 	}
    181      1.1   brezak 	(void) fputc('\n', DbgFp);
    182      1.1   brezak 	(void) fflush(DbgFp);
    183      1.1   brezak 
    184      1.1   brezak 	(void) sigsetmask(omask);		/* reset old signal mask */
    185      1.1   brezak }
    186      1.1   brezak 
    187      1.1   brezak 
    188      1.1   brezak /*
    189      1.1   brezak **  GetEtherAddr -- convert an RMP (Ethernet) address into a string.
    190      1.1   brezak **
    191      1.1   brezak **	An RMP BOOT packet has been received.  Look at the type field
    192      1.1   brezak **	and process Boot Requests, Read Requests, and Boot Complete
    193      1.1   brezak **	packets.  Any other type will be dropped with a warning msg.
    194      1.1   brezak **
    195      1.1   brezak **	Parameters:
    196      1.1   brezak **		addr - array of RMP_ADDRLEN bytes.
    197      1.1   brezak **
    198      1.1   brezak **	Returns:
    199      1.1   brezak **		Pointer to static string representation of `addr'.
    200      1.1   brezak **
    201      1.1   brezak **	Side Effects:
    202      1.1   brezak **		None.
    203      1.1   brezak **
    204      1.1   brezak **	Warnings:
    205      1.1   brezak **		- The return value points to a static buffer; it must
    206      1.1   brezak **		  be copied if it's to be saved.
    207      1.1   brezak */
    208      1.1   brezak char *
    209      1.1   brezak GetEtherAddr(addr)
    210      1.5  thorpej 	u_int8_t *addr;
    211      1.1   brezak {
    212      1.1   brezak 	static char Hex[] = "0123456789abcdef";
    213      1.1   brezak 	static char etherstr[RMP_ADDRLEN*3];
    214      1.1   brezak 	register int i;
    215      1.5  thorpej 	register char *cp;
    216      1.1   brezak 
    217      1.1   brezak 	/*
    218      1.1   brezak 	 *  For each byte in `addr', convert it to "<hexchar><hexchar>:".
    219      1.1   brezak 	 *  The last byte does not get a trailing `:' appended.
    220      1.1   brezak 	 */
    221      1.1   brezak 	i = 0;
    222      1.5  thorpej 	cp = etherstr;
    223      1.1   brezak 	for(;;) {
    224      1.5  thorpej 		*cp++ = Hex[*addr >> 4 & 0xf];
    225      1.5  thorpej 		*cp++ = Hex[*addr++ & 0xf];
    226      1.1   brezak 		if (++i == RMP_ADDRLEN)
    227      1.1   brezak 			break;
    228      1.5  thorpej 		*cp++ = ':';
    229      1.1   brezak 	}
    230      1.5  thorpej 	*cp = '\0';
    231      1.1   brezak 
    232      1.1   brezak 	return(etherstr);
    233      1.1   brezak }
    234      1.1   brezak 
    235      1.1   brezak 
    236      1.1   brezak /*
    237      1.1   brezak **  DispFlnm -- Print a string of bytes to DbgFp (often, a file name).
    238      1.1   brezak **
    239      1.1   brezak **	Parameters:
    240      1.1   brezak **		size - number of bytes to print.
    241      1.1   brezak **		flnm - address of first byte.
    242      1.1   brezak **
    243      1.1   brezak **	Returns:
    244      1.1   brezak **		Nothing.
    245      1.1   brezak **
    246      1.1   brezak **	Side Effects:
    247      1.1   brezak **		- Characters are sent to `DbgFp'.
    248      1.1   brezak */
    249      1.1   brezak void
    250      1.1   brezak DspFlnm(size, flnm)
    251      1.1   brezak 	register u_int size;
    252      1.1   brezak 	register char *flnm;
    253      1.1   brezak {
    254      1.1   brezak 	register int i;
    255      1.1   brezak 
    256      1.5  thorpej 	(void) fprintf(DbgFp, "\n\t\tFile Name (%u): <", size);
    257      1.1   brezak 	for (i = 0; i < size; i++)
    258      1.1   brezak 		(void) fputc(*flnm++, DbgFp);
    259      1.1   brezak 	(void) fputs(">\n", DbgFp);
    260      1.1   brezak }
    261      1.1   brezak 
    262      1.1   brezak 
    263      1.1   brezak /*
    264      1.1   brezak **  NewClient -- allocate memory for a new CLIENT.
    265      1.1   brezak **
    266      1.1   brezak **	Parameters:
    267      1.1   brezak **		addr - RMP (Ethernet) address of new client.
    268      1.1   brezak **
    269      1.1   brezak **	Returns:
    270      1.1   brezak **		Ptr to new CLIENT or NULL if we ran out of memory.
    271      1.1   brezak **
    272      1.1   brezak **	Side Effects:
    273      1.1   brezak **		- Memory will be malloc'd for the new CLIENT.
    274      1.1   brezak **		- If malloc() fails, a log message will be generated.
    275      1.1   brezak */
    276      1.1   brezak CLIENT *
    277      1.1   brezak NewClient(addr)
    278      1.5  thorpej 	u_int8_t *addr;
    279      1.1   brezak {
    280      1.1   brezak 	CLIENT *ctmp;
    281      1.1   brezak 
    282      1.1   brezak 	if ((ctmp = (CLIENT *) malloc(sizeof(CLIENT))) == NULL) {
    283      1.1   brezak 		syslog(LOG_ERR, "NewClient: out of memory (%s)",
    284      1.1   brezak 		       GetEtherAddr(addr));
    285      1.1   brezak 		return(NULL);
    286      1.1   brezak 	}
    287      1.1   brezak 
    288      1.1   brezak 	bzero(ctmp, sizeof(CLIENT));
    289      1.1   brezak 	bcopy(addr, &ctmp->addr[0], RMP_ADDRLEN);
    290      1.1   brezak 	return(ctmp);
    291      1.1   brezak }
    292      1.1   brezak 
    293      1.1   brezak /*
    294      1.1   brezak **  FreeClient -- free linked list of Clients.
    295      1.1   brezak **
    296      1.1   brezak **	Parameters:
    297      1.1   brezak **		None.
    298      1.1   brezak **
    299      1.1   brezak **	Returns:
    300      1.1   brezak **		Nothing.
    301      1.1   brezak **
    302      1.1   brezak **	Side Effects:
    303      1.1   brezak **		- All malloc'd memory associated with the linked list of
    304      1.1   brezak **		  CLIENTS will be free'd; `Clients' will be set to NULL.
    305      1.1   brezak **
    306      1.1   brezak **	Warnings:
    307      1.1   brezak **		- This routine must be called with SIGHUP blocked.
    308      1.1   brezak */
    309      1.1   brezak void
    310      1.1   brezak FreeClients()
    311      1.1   brezak {
    312      1.1   brezak 	register CLIENT *ctmp;
    313      1.1   brezak 
    314      1.1   brezak 	while (Clients != NULL) {
    315      1.1   brezak 		ctmp = Clients;
    316      1.1   brezak 		Clients = Clients->next;
    317      1.1   brezak 		FreeClient(ctmp);
    318      1.1   brezak 	}
    319      1.1   brezak }
    320      1.1   brezak 
    321      1.1   brezak /*
    322      1.1   brezak **  NewStr -- allocate memory for a character array.
    323      1.1   brezak **
    324      1.1   brezak **	Parameters:
    325      1.1   brezak **		str - null terminated character array.
    326      1.1   brezak **
    327      1.1   brezak **	Returns:
    328      1.1   brezak **		Ptr to new character array or NULL if we ran out of memory.
    329      1.1   brezak **
    330      1.1   brezak **	Side Effects:
    331      1.1   brezak **		- Memory will be malloc'd for the new character array.
    332      1.1   brezak **		- If malloc() fails, a log message will be generated.
    333      1.1   brezak */
    334      1.1   brezak char *
    335      1.1   brezak NewStr(str)
    336      1.1   brezak 	char *str;
    337      1.1   brezak {
    338      1.1   brezak 	char *stmp;
    339      1.1   brezak 
    340      1.1   brezak 	if ((stmp = (char *)malloc((unsigned) (strlen(str)+1))) == NULL) {
    341      1.1   brezak 		syslog(LOG_ERR, "NewStr: out of memory (%s)", str);
    342      1.1   brezak 		return(NULL);
    343      1.1   brezak 	}
    344      1.1   brezak 
    345      1.1   brezak 	(void) strcpy(stmp, str);
    346      1.1   brezak 	return(stmp);
    347      1.1   brezak }
    348      1.1   brezak 
    349      1.1   brezak /*
    350      1.1   brezak **  To save time, NewConn and FreeConn maintain a cache of one RMPCONN
    351      1.1   brezak **  in `LastFree' (defined below).
    352      1.1   brezak */
    353      1.1   brezak 
    354      1.1   brezak static RMPCONN *LastFree = NULL;
    355      1.1   brezak 
    356      1.1   brezak /*
    357      1.1   brezak **  NewConn -- allocate memory for a new RMPCONN connection.
    358      1.1   brezak **
    359      1.1   brezak **	Parameters:
    360      1.1   brezak **		rconn - initialization template for new connection.
    361      1.1   brezak **
    362      1.1   brezak **	Returns:
    363      1.1   brezak **		Ptr to new RMPCONN or NULL if we ran out of memory.
    364      1.1   brezak **
    365      1.1   brezak **	Side Effects:
    366      1.1   brezak **		- Memory may be malloc'd for the new RMPCONN (if not cached).
    367      1.1   brezak **		- If malloc() fails, a log message will be generated.
    368      1.1   brezak */
    369      1.1   brezak RMPCONN *
    370      1.1   brezak NewConn(rconn)
    371      1.1   brezak 	RMPCONN *rconn;
    372      1.1   brezak {
    373      1.1   brezak 	RMPCONN *rtmp;
    374      1.1   brezak 
    375      1.1   brezak 	if (LastFree == NULL) {		/* nothing cached; make a new one */
    376      1.1   brezak 		if ((rtmp = (RMPCONN *) malloc(sizeof(RMPCONN))) == NULL) {
    377      1.1   brezak 			syslog(LOG_ERR, "NewConn: out of memory (%s)",
    378      1.1   brezak 			       EnetStr(rconn));
    379      1.1   brezak 			return(NULL);
    380      1.1   brezak 		}
    381      1.1   brezak 	} else {			/* use the cached RMPCONN */
    382      1.1   brezak 		rtmp = LastFree;
    383      1.1   brezak 		LastFree = NULL;
    384      1.1   brezak 	}
    385      1.1   brezak 
    386      1.1   brezak 	/*
    387      1.1   brezak 	 *  Copy template into `rtmp', init file descriptor to `-1' and
    388      1.1   brezak 	 *  set ptr to next elem NULL.
    389      1.1   brezak 	 */
    390      1.1   brezak 	bcopy((char *)rconn, (char *)rtmp, sizeof(RMPCONN));
    391      1.1   brezak 	rtmp->bootfd = -1;
    392      1.1   brezak 	rtmp->next = NULL;
    393      1.1   brezak 
    394      1.1   brezak 	return(rtmp);
    395      1.1   brezak }
    396      1.1   brezak 
    397      1.1   brezak /*
    398      1.1   brezak **  FreeConn -- Free memory associated with an RMPCONN connection.
    399      1.1   brezak **
    400      1.1   brezak **	Parameters:
    401      1.1   brezak **		rtmp - ptr to RMPCONN to be free'd.
    402      1.1   brezak **
    403      1.1   brezak **	Returns:
    404      1.1   brezak **		Nothing.
    405      1.1   brezak **
    406      1.1   brezak **	Side Effects:
    407      1.1   brezak **		- Memory associated with `rtmp' may be free'd (or cached).
    408      1.1   brezak **		- File desc associated with `rtmp->bootfd' will be closed.
    409      1.1   brezak */
    410      1.1   brezak void
    411      1.1   brezak FreeConn(rtmp)
    412      1.1   brezak 	register RMPCONN *rtmp;
    413      1.1   brezak {
    414      1.1   brezak 	/*
    415      1.1   brezak 	 *  If the file descriptor is in use, close the file.
    416      1.1   brezak 	 */
    417      1.1   brezak 	if (rtmp->bootfd >= 0) {
    418      1.1   brezak 		(void) close(rtmp->bootfd);
    419      1.1   brezak 		rtmp->bootfd = -1;
    420      1.1   brezak 	}
    421      1.1   brezak 
    422      1.1   brezak 	if (LastFree == NULL)		/* cache for next time */
    423      1.1   brezak 		rtmp = LastFree;
    424      1.1   brezak 	else				/* already one cached; free this one */
    425      1.1   brezak 		free((char *)rtmp);
    426      1.1   brezak }
    427      1.1   brezak 
    428      1.1   brezak /*
    429      1.1   brezak **  FreeConns -- free linked list of RMPCONN connections.
    430      1.1   brezak **
    431      1.1   brezak **	Parameters:
    432      1.1   brezak **		None.
    433      1.1   brezak **
    434      1.1   brezak **	Returns:
    435      1.1   brezak **		Nothing.
    436      1.1   brezak **
    437      1.1   brezak **	Side Effects:
    438      1.1   brezak **		- All malloc'd memory associated with the linked list of
    439      1.1   brezak **		  connections will be free'd; `RmpConns' will be set to NULL.
    440      1.1   brezak **		- If LastFree is != NULL, it too will be free'd & NULL'd.
    441      1.1   brezak **
    442      1.1   brezak **	Warnings:
    443      1.1   brezak **		- This routine must be called with SIGHUP blocked.
    444      1.1   brezak */
    445      1.1   brezak void
    446      1.1   brezak FreeConns()
    447      1.1   brezak {
    448      1.1   brezak 	register RMPCONN *rtmp;
    449      1.1   brezak 
    450      1.1   brezak 	while (RmpConns != NULL) {
    451      1.1   brezak 		rtmp = RmpConns;
    452      1.1   brezak 		RmpConns = RmpConns->next;
    453      1.1   brezak 		FreeConn(rtmp);
    454      1.1   brezak 	}
    455      1.1   brezak 
    456      1.1   brezak 	if (LastFree != NULL) {
    457      1.1   brezak 		free((char *)LastFree);
    458      1.1   brezak 		LastFree = NULL;
    459      1.1   brezak 	}
    460      1.1   brezak }
    461      1.1   brezak 
    462      1.1   brezak /*
    463      1.1   brezak **  AddConn -- Add a connection to the linked list of connections.
    464      1.1   brezak **
    465      1.1   brezak **	Parameters:
    466      1.1   brezak **		rconn - connection to be added.
    467      1.1   brezak **
    468      1.1   brezak **	Returns:
    469      1.1   brezak **		Nothing.
    470      1.1   brezak **
    471      1.1   brezak **	Side Effects:
    472      1.1   brezak **		- RmpConn will point to new connection.
    473      1.1   brezak **
    474      1.1   brezak **	Warnings:
    475      1.1   brezak **		- This routine must be called with SIGHUP blocked.
    476      1.1   brezak */
    477      1.1   brezak void
    478      1.1   brezak AddConn(rconn)
    479      1.1   brezak 	register RMPCONN *rconn;
    480      1.1   brezak {
    481      1.1   brezak 	if (RmpConns != NULL)
    482      1.1   brezak 		rconn->next = RmpConns;
    483      1.1   brezak 	RmpConns = rconn;
    484      1.1   brezak }
    485      1.1   brezak 
    486      1.1   brezak /*
    487      1.1   brezak **  FindConn -- Find a connection in the linked list of connections.
    488      1.1   brezak **
    489      1.1   brezak **	We use the RMP (Ethernet) address as the basis for determining
    490      1.1   brezak **	if this is the same connection.  According to the Remote Maint
    491      1.1   brezak **	Protocol, we can only have one connection with any machine.
    492      1.1   brezak **
    493      1.1   brezak **	Parameters:
    494      1.1   brezak **		rconn - connection to be found.
    495      1.1   brezak **
    496      1.1   brezak **	Returns:
    497      1.1   brezak **		Matching connection from linked list or NULL if not found.
    498      1.1   brezak **
    499      1.1   brezak **	Side Effects:
    500      1.1   brezak **		None.
    501      1.1   brezak **
    502      1.1   brezak **	Warnings:
    503      1.1   brezak **		- This routine must be called with SIGHUP blocked.
    504      1.1   brezak */
    505      1.1   brezak RMPCONN *
    506      1.1   brezak FindConn(rconn)
    507      1.1   brezak 	register RMPCONN *rconn;
    508      1.1   brezak {
    509      1.1   brezak 	register RMPCONN *rtmp;
    510      1.1   brezak 
    511      1.1   brezak 	for (rtmp = RmpConns; rtmp != NULL; rtmp = rtmp->next)
    512      1.1   brezak 		if (bcmp((char *)&rconn->rmp.hp_hdr.saddr[0],
    513      1.1   brezak 		         (char *)&rtmp->rmp.hp_hdr.saddr[0], RMP_ADDRLEN) == 0)
    514      1.1   brezak 			break;
    515      1.1   brezak 
    516      1.1   brezak 	return(rtmp);
    517      1.1   brezak }
    518      1.1   brezak 
    519      1.1   brezak /*
    520      1.1   brezak **  RemoveConn -- Remove a connection from the linked list of connections.
    521      1.1   brezak **
    522      1.1   brezak **	Parameters:
    523      1.1   brezak **		rconn - connection to be removed.
    524      1.1   brezak **
    525      1.1   brezak **	Returns:
    526      1.1   brezak **		Nothing.
    527      1.1   brezak **
    528      1.1   brezak **	Side Effects:
    529      1.1   brezak **		- If found, an RMPCONN will cease to exist and it will
    530      1.1   brezak **		  be removed from the linked list.
    531      1.1   brezak **
    532      1.1   brezak **	Warnings:
    533      1.1   brezak **		- This routine must be called with SIGHUP blocked.
    534      1.1   brezak */
    535      1.1   brezak void
    536      1.1   brezak RemoveConn(rconn)
    537      1.1   brezak 	register RMPCONN *rconn;
    538      1.1   brezak {
    539      1.1   brezak 	register RMPCONN *thisrconn, *lastrconn;
    540      1.1   brezak 
    541      1.1   brezak 	if (RmpConns == rconn) {		/* easy case */
    542      1.1   brezak 		RmpConns = RmpConns->next;
    543      1.1   brezak 		FreeConn(rconn);
    544      1.1   brezak 	} else {				/* must traverse linked list */
    545      1.1   brezak 		lastrconn = RmpConns;			/* set back ptr */
    546      1.1   brezak 		thisrconn = lastrconn->next;		/* set current ptr */
    547      1.1   brezak 		while (thisrconn != NULL) {
    548      1.1   brezak 			if (rconn == thisrconn) {		/* found it */
    549      1.1   brezak 				lastrconn->next = thisrconn->next;
    550      1.1   brezak 				FreeConn(thisrconn);
    551      1.1   brezak 				break;
    552      1.1   brezak 			}
    553      1.1   brezak 			lastrconn = thisrconn;
    554      1.1   brezak 			thisrconn = thisrconn->next;
    555      1.1   brezak 		}
    556      1.1   brezak 	}
    557      1.1   brezak }
    558