11541Srgrimes/* 21541Srgrimes * Copyright (c) 1988, 1992 The University of Utah and the Center 31541Srgrimes * for Software Science (CSS). 41541Srgrimes * Copyright (c) 1992, 1993 51541Srgrimes * The Regents of the University of California. All rights reserved. 61541Srgrimes * 71541Srgrimes * This code is derived from software contributed to Berkeley by 81541Srgrimes * the Center for Software Science of the University of Utah Computer 91541Srgrimes * Science Department. CSS requests users of this software to return 101541Srgrimes * to css-dist@cs.utah.edu any improvements that they make and grant 111541Srgrimes * CSS redistribution rights. 121541Srgrimes * 131541Srgrimes * Redistribution and use in source and binary forms, with or without 141541Srgrimes * modification, are permitted provided that the following conditions 151541Srgrimes * are met: 161541Srgrimes * 1. Redistributions of source code must retain the above copyright 171541Srgrimes * notice, this list of conditions and the following disclaimer. 181541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 191541Srgrimes * notice, this list of conditions and the following disclaimer in the 201541Srgrimes * documentation and/or other materials provided with the distribution. 211541Srgrimes * 3. Neither the name of the University nor the names of its contributors 221541Srgrimes * may be used to endorse or promote products derived from this software 231541Srgrimes * without specific prior written permission. 241541Srgrimes * 251541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 261541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 271541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 281541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 291541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 301541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 311541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 321541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 331541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 341541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 351541Srgrimes * SUCH DAMAGE. 3636503Speter * 371541Srgrimes * from: @(#)rmpproto.c 8.1 (Berkeley) 6/4/93 381541Srgrimes * 3983651Speter * From: Utah Hdr: rmpproto.c 3.1 92/07/06 4083651Speter * Author: Jeff Forys, University of Utah CSS 4183651Speter */ 421541Srgrimes 431541Srgrimes#ifndef lint 441541Srgrimes#if 0 451541Srgrimesstatic const char sccsid[] = "@(#)rmpproto.c 8.1 (Berkeley) 6/4/93"; 461541Srgrimes#endif 4783651Speterstatic const char rcsid[] = 481541Srgrimes "$FreeBSD: releng/11.0/libexec/rbootd/rmpproto.c 262136 2014-02-17 22:27:32Z brueffer $"; 4948274Speter#endif /* not lint */ 5048274Speter 5160041Sphk#include <sys/param.h> 5231886Sbde#include <sys/time.h> 531541Srgrimes#include <netinet/in.h> 541541Srgrimes 551541Srgrimes#include <errno.h> 561541Srgrimes#include <fcntl.h> 571541Srgrimes#include <stdio.h> 581541Srgrimes#include <string.h> 591541Srgrimes#include <syslog.h> 609336Sdfr#include <unistd.h> 612997Swollman#include "defs.h" 622997Swollman 6383651Speter/* 641541Srgrimes** ProcessPacket -- determine packet type and do what's required. 653305Sphk** 6612662Sdg** An RMP BOOT packet has been received. Look at the type field 6712662Sdg** and process Boot Requests, Read Requests, and Boot Complete 6892783Sjeff** packets. Any other type will be dropped with a warning msg. 693305Sphk** 701541Srgrimes** Parameters: 719336Sdfr** rconn - the new connection 7283651Speter** client - list of files available to this host 7383651Speter** 741541Srgrimes** Returns: 7583651Speter** Nothing. 7683651Speter** 771541Srgrimes** Side Effects: 781541Srgrimes** - If this is a valid boot request, it will be added to 791541Srgrimes** the linked list of outstanding requests (RmpConns). 801541Srgrimes** - If this is a valid boot complete, its associated 811541Srgrimes** entry in RmpConns will be deleted. 821541Srgrimes** - Also, unless we run out of memory, a reply will be 831541Srgrimes** sent to the host that sent the packet. 8483651Speter*/ 8583651Spetervoid 8683651SpeterProcessPacket(RMPCONN *rconn, CLIENT *client) 8783651Speter{ 881541Srgrimes struct rmp_packet *rmp; 891541Srgrimes RMPCONN *rconnout; 9036541Speter 9112911Sphk rmp = &rconn->rmp; /* cache pointer to RMP packet */ 9283651Speter 9312911Sphk switch(rmp->r_type) { /* do what we came here to do */ 9412911Sphk case RMP_BOOT_REQ: /* boot request */ 9583651Speter if ((rconnout = NewConn(rconn)) == NULL) 9683651Speter return; 979336Sdfr 9883651Speter /* 9983651Speter * If the Session ID is 0xffff, this is a "probe" 1009759Sbde * packet and we do not want to add the connection 10183651Speter * to the linked list of active connections. There 10283651Speter * are two types of probe packets, if the Sequence 10338894Sbde * Number is 0 they want to know our host name, o/w 1049336Sdfr * they want the name of the file associated with 1059336Sdfr * the number spec'd by the Sequence Number. 1069336Sdfr * 1079336Sdfr * If this is an actual boot request, open the file 1089336Sdfr * and send a reply. If SendBootRepl() does not 1099336Sdfr * return 0, add the connection to the linked list 1109336Sdfr * of active connections, otherwise delete it since 1119336Sdfr * an error was encountered. 1129336Sdfr */ 1139336Sdfr if (ntohs(rmp->r_brq.rmp_session) == RMP_PROBESID) { 1149336Sdfr if (WORDZE(rmp->r_brq.rmp_seqno)) 1159336Sdfr (void) SendServerID(rconnout); 1169336Sdfr else 1179336Sdfr (void) SendFileNo(rmp, rconnout, 1189336Sdfr client? client->files: 1199336Sdfr BootFiles); 1209336Sdfr FreeConn(rconnout); 1219336Sdfr } else { 1229336Sdfr if (SendBootRepl(rmp, rconnout, 1239336Sdfr client? client->files: BootFiles)) 1249336Sdfr AddConn(rconnout); 1259336Sdfr else 1269336Sdfr FreeConn(rconnout); 1279336Sdfr } 1289336Sdfr break; 1299336Sdfr 1309336Sdfr case RMP_BOOT_REPL: /* boot reply (not valid) */ 1319336Sdfr syslog(LOG_WARNING, "%s: sent a boot reply", 1329336Sdfr EnetStr(rconn)); 13360938Sjake break; 1343664Sphk 1351541Srgrimes case RMP_READ_REQ: /* read request */ 1361541Srgrimes /* 1371541Srgrimes * Send a portion of the boot file. 1381541Srgrimes */ 1391541Srgrimes (void) SendReadRepl(rconn); 1401541Srgrimes break; 14183651Speter 1421541Srgrimes case RMP_READ_REPL: /* read reply (not valid) */ 14383651Speter syslog(LOG_WARNING, "%s: sent a read reply", 1441541Srgrimes EnetStr(rconn)); 14570254Sbmilekic break; 1461541Srgrimes 14770254Sbmilekic case RMP_BOOT_DONE: /* boot complete */ 1481541Srgrimes /* 1491541Srgrimes * Remove the entry from the linked list of active 1501541Srgrimes * connections. 1511541Srgrimes */ 1521541Srgrimes (void) BootDone(rconn); 1531541Srgrimes break; 1541541Srgrimes 1551541Srgrimes default: /* unknown RMP packet type */ 1561541Srgrimes syslog(LOG_WARNING, "%s: unknown packet type (%u)", 1571541Srgrimes EnetStr(rconn), rmp->r_type); 1581541Srgrimes } 15983651Speter} 16083651Speter 16183651Speter/* 1621541Srgrimes** SendServerID -- send our host name to who ever requested it. 16383651Speter** 16483651Speter** Parameters: 16583651Speter** rconn - the reply packet to be formatted. 16683651Speter** 16783651Speter** Returns: 16883651Speter** 1 on success, 0 on failure. 1691541Srgrimes** 1701541Srgrimes** Side Effects: 17170254Sbmilekic** none. 1729336Sdfr*/ 17370254Sbmilekicint 1749336SdfrSendServerID(RMPCONN *rconn) 1759336Sdfr{ 1761541Srgrimes struct rmp_packet *rpl; 1779336Sdfr char *src, *dst; 1781541Srgrimes u_int8_t *size; 1791541Srgrimes 1801541Srgrimes rpl = &rconn->rmp; /* cache ptr to RMP packet */ 1811541Srgrimes 1821541Srgrimes /* 1831541Srgrimes * Set up assorted fields in reply packet. 1841541Srgrimes */ 1851541Srgrimes rpl->r_brpl.rmp_type = RMP_BOOT_REPL; 18684002Speter rpl->r_brpl.rmp_retcode = RMP_E_OKAY; 18717186Sdfr ZEROWORD(rpl->r_brpl.rmp_seqno); 18835066Sphk rpl->r_brpl.rmp_session = 0; 18983651Speter rpl->r_brpl.rmp_version = htons(RMP_VERSION); 19035066Sphk 19117186Sdfr size = &rpl->r_brpl.rmp_flnmsize; /* ptr to length of host name */ 19217186Sdfr 19317186Sdfr /* 1941541Srgrimes * Copy our host name into the reply packet incrementing the 1951541Srgrimes * length as we go. Stop at RMP_HOSTLEN or the first dot. 19617186Sdfr */ 1971541Srgrimes src = MyHost; 1981541Srgrimes dst = (char *) &rpl->r_brpl.rmp_flnm; 1991541Srgrimes for (*size = 0; *size < RMP_HOSTLEN; (*size)++) { 20083651Speter if (*src == '.' || *src == '\0') 20183651Speter break; 20283651Speter *dst++ = *src++; 20383651Speter } 2041541Srgrimes 20583651Speter rconn->rmplen = RMPBOOTSIZE(*size); /* set packet length */ 20683651Speter 2071541Srgrimes return(SendPacket(rconn)); /* send packet */ 2081541Srgrimes} 2091541Srgrimes 2101541Srgrimes/* 2111541Srgrimes** SendFileNo -- send the name of a bootable file to the requester. 2121541Srgrimes** 2131541Srgrimes** Parameters: 2141541Srgrimes** req - RMP BOOT packet containing the request. 2151541Srgrimes** rconn - the reply packet to be formatted. 21684002Speter** filelist - list of files available to the requester. 2171541Srgrimes** 2181541Srgrimes** Returns: 2191541Srgrimes** 1 on success, 0 on failure. 2201541Srgrimes** 2211541Srgrimes** Side Effects: 2221541Srgrimes** none. 2231541Srgrimes*/ 2241541Srgrimesint 2251541SrgrimesSendFileNo(struct rmp_packet *req, RMPCONN *rconn, char *filelist[]) 22683651Speter{ 2279336Sdfr struct rmp_packet *rpl; 2289336Sdfr char *src, *dst; 2299336Sdfr u_int8_t *size; 2309336Sdfr int i; 23184002Speter 23283651Speter GETWORD(req->r_brpl.rmp_seqno, i); /* SeqNo is really FileNo */ 23383651Speter rpl = &rconn->rmp; /* cache ptr to RMP packet */ 2341541Srgrimes 2359336Sdfr /* 2361541Srgrimes * Set up assorted fields in reply packet. 2371541Srgrimes */ 2381541Srgrimes rpl->r_brpl.rmp_type = RMP_BOOT_REPL; 2391541Srgrimes PUTWORD(i, rpl->r_brpl.rmp_seqno); 2401541Srgrimes i--; 2411541Srgrimes rpl->r_brpl.rmp_session = 0; 24217186Sdfr rpl->r_brpl.rmp_version = htons(RMP_VERSION); 24317186Sdfr 2441541Srgrimes size = &rpl->r_brpl.rmp_flnmsize; /* ptr to length of filename */ 2451549Srgrimes *size = 0; /* init length to zero */ 24683651Speter 2471541Srgrimes /* 24883651Speter * Copy the file name into the reply packet incrementing the 24983651Speter * length as we go. Stop at end of string or when RMPBOOTDATA 25083651Speter * characters have been copied. Also, set return code to 2511541Srgrimes * indicate success or "no more files". 2521541Srgrimes */ 2531541Srgrimes if (i < C_MAXFILE && filelist[i] != NULL) { 25436519Speter src = filelist[i]; 25517186Sdfr dst = (char *)&rpl->r_brpl.rmp_flnm; 25617186Sdfr for (; *src && *size < RMPBOOTDATA; (*size)++) { 25736519Speter if (*src == '\0') 25817186Sdfr break; 2591541Srgrimes *dst++ = *src++; 2601541Srgrimes } 2611541Srgrimes rpl->r_brpl.rmp_retcode = RMP_E_OKAY; 2621541Srgrimes } else 2631541Srgrimes rpl->r_brpl.rmp_retcode = RMP_E_NODFLT; 2641541Srgrimes 2651541Srgrimes rconn->rmplen = RMPBOOTSIZE(*size); /* set packet length */ 2661541Srgrimes 2671541Srgrimes return(SendPacket(rconn)); /* send packet */ 2681541Srgrimes} 2691541Srgrimes 2701541Srgrimes/* 2711541Srgrimes** SendBootRepl -- open boot file and respond to boot request. 2721541Srgrimes** 2731541Srgrimes** Parameters: 27470254Sbmilekic** req - RMP BOOT packet containing the request. 2751541Srgrimes** rconn - the reply packet to be formatted. 27670254Sbmilekic** filelist - list of files available to the requester. 2771541Srgrimes** 2781541Srgrimes** Returns: 2791541Srgrimes** 1 on success, 0 on failure. 2801541Srgrimes** 2811541Srgrimes** Side Effects: 2821541Srgrimes** none. 2831541Srgrimes*/ 2841541Srgrimesint 2851541SrgrimesSendBootRepl(struct rmp_packet *req, RMPCONN *rconn, char *filelist[]) 2861541Srgrimes{ 2871541Srgrimes int retval; 2881541Srgrimes char *filename, filepath[RMPBOOTDATA+1]; 2891541Srgrimes RMPCONN *oldconn; 2901541Srgrimes struct rmp_packet *rpl; 2911541Srgrimes char *src, *dst1, *dst2; 2921541Srgrimes u_int8_t i; 2931541Srgrimes 2941541Srgrimes /* 2951541Srgrimes * If another connection already exists, delete it since we 2961541Srgrimes * are obviously starting again. 2971541Srgrimes */ 2981541Srgrimes if ((oldconn = FindConn(rconn)) != NULL) { 2991541Srgrimes syslog(LOG_WARNING, "%s: dropping existing connection", 30017186Sdfr EnetStr(oldconn)); 30117186Sdfr RemoveConn(oldconn); 3021541Srgrimes } 3031541Srgrimes 3041541Srgrimes rpl = &rconn->rmp; /* cache ptr to RMP packet */ 3051541Srgrimes 30670254Sbmilekic /* 3071541Srgrimes * Set up assorted fields in reply packet. 3081541Srgrimes */ 3091541Srgrimes rpl->r_brpl.rmp_type = RMP_BOOT_REPL; 3101541Srgrimes COPYWORD(req->r_brq.rmp_seqno, rpl->r_brpl.rmp_seqno); 3111541Srgrimes rpl->r_brpl.rmp_session = htons(GenSessID()); 3121541Srgrimes rpl->r_brpl.rmp_version = htons(RMP_VERSION); 3131541Srgrimes rpl->r_brpl.rmp_flnmsize = req->r_brq.rmp_flnmsize; 3141541Srgrimes 3151541Srgrimes /* 3161541Srgrimes * Copy file name to `filepath' string, and into reply packet. 3171541Srgrimes */ 3181541Srgrimes src = &req->r_brq.rmp_flnm; 3191541Srgrimes dst1 = filepath; 3201541Srgrimes dst2 = &rpl->r_brpl.rmp_flnm; 3211541Srgrimes for (i = 0; i < req->r_brq.rmp_flnmsize; i++) 3221541Srgrimes *dst1++ = *dst2++ = *src++; 3231541Srgrimes *dst1 = '\0'; 3241549Srgrimes 32583651Speter /* 3261541Srgrimes * If we are booting HP-UX machines, their secondary loader will 32783651Speter * ask for files like "/hp-ux". As a security measure, we do not 3281541Srgrimes * allow boot files to lay outside the boot directory (unless they 32936541Speter * are purposely link'd out. So, make `filename' become the path- 3301541Srgrimes * stripped file name and spoof the client into thinking that it 3311541Srgrimes * really got what it wanted. 3321541Srgrimes */ 3331541Srgrimes filename = (filename = strrchr(filepath,'/'))? ++filename: filepath; 3341541Srgrimes 3351541Srgrimes /* 33636541Speter * Check that this is a valid boot file name. 3371541Srgrimes */ 3381541Srgrimes for (i = 0; i < C_MAXFILE && filelist[i] != NULL; i++) 3391541Srgrimes if (STREQN(filename, filelist[i])) 3401541Srgrimes goto match; 3411541Srgrimes 3421541Srgrimes /* 3431541Srgrimes * Invalid boot file name, set error and send reply packet. 3441541Srgrimes */ 3451541Srgrimes rpl->r_brpl.rmp_retcode = RMP_E_NOFILE; 3461541Srgrimes retval = 0; 3471541Srgrimes goto sendpkt; 3481541Srgrimes 3491541Srgrimesmatch: 3501541Srgrimes /* 35170254Sbmilekic * This is a valid boot file. Open the file and save the file 3521541Srgrimes * descriptor associated with this connection and set success 35370254Sbmilekic * indication. If the file couldnt be opened, set error: 3541541Srgrimes * "no such file or dir" - RMP_E_NOFILE 3551541Srgrimes * "file table overflow" - RMP_E_BUSY 3561541Srgrimes * "too many open files" - RMP_E_BUSY 35736541Speter * anything else - RMP_E_OPENFILE 3581541Srgrimes */ 3591541Srgrimes if ((rconn->bootfd = open(filename, O_RDONLY, 0600)) < 0) { 3601541Srgrimes rpl->r_brpl.rmp_retcode = (errno == ENOENT)? RMP_E_NOFILE: 3611541Srgrimes (errno == EMFILE || errno == ENFILE)? RMP_E_BUSY: 3621541Srgrimes RMP_E_OPENFILE; 3631541Srgrimes retval = 0; 3641541Srgrimes } else { 3651541Srgrimes rpl->r_brpl.rmp_retcode = RMP_E_OKAY; 3661541Srgrimes retval = 1; 3671541Srgrimes } 3681541Srgrimes 3691541Srgrimessendpkt: 3701541Srgrimes syslog(LOG_INFO, "%s: request to boot %s (%s)", 3711541Srgrimes EnetStr(rconn), filename, retval? "granted": "denied"); 3721541Srgrimes 3731541Srgrimes rconn->rmplen = RMPBOOTSIZE(rpl->r_brpl.rmp_flnmsize); 3741541Srgrimes 3751541Srgrimes return (retval & SendPacket(rconn)); 3761541Srgrimes} 3771541Srgrimes 3781541Srgrimes/* 3791541Srgrimes** SendReadRepl -- send a portion of the boot file to the requester. 3801541Srgrimes** 3811541Srgrimes** Parameters: 3821541Srgrimes** rconn - the reply packet to be formatted. 3831541Srgrimes** 3841541Srgrimes** Returns: 3851541Srgrimes** 1 on success, 0 on failure. 3861549Srgrimes** 38783651Speter** Side Effects: 3881541Srgrimes** none. 38983651Speter*/ 3901541Srgrimesint 39192783SjeffSendReadRepl(RMPCONN *rconn) 39292783Sjeff{ 3931541Srgrimes int retval = 0; 3941541Srgrimes RMPCONN *oldconn; 3951541Srgrimes struct rmp_packet *rpl, *req; 3961541Srgrimes int size = 0; 3971541Srgrimes int madeconn = 0; 3981541Srgrimes 3991541Srgrimes /* 4001541Srgrimes * Find the old connection. If one doesn't exist, create one only 4011541Srgrimes * to return the error code. 4021541Srgrimes */ 4033664Sphk if ((oldconn = FindConn(rconn)) == NULL) { 4049336Sdfr if ((oldconn = NewConn(rconn)) == NULL) 4059336Sdfr return(0); 4069336Sdfr syslog(LOG_ERR, "SendReadRepl: no active connection (%s)", 4071541Srgrimes EnetStr(rconn)); 40819449Sdfr madeconn++; 4091541Srgrimes } 41019449Sdfr 41119449Sdfr req = &rconn->rmp; /* cache ptr to request packet */ 4121541Srgrimes rpl = &oldconn->rmp; /* cache ptr to reply packet */ 4131541Srgrimes 4141541Srgrimes if (madeconn) { /* no active connection above; abort */ 4151541Srgrimes rpl->r_rrpl.rmp_retcode = RMP_E_ABORT; 4161541Srgrimes retval = 1; 4173664Sphk goto sendpkt; 41816365Sphk } 4193305Sphk 4201549Srgrimes /* 42183651Speter * Make sure Session ID's match. 42283651Speter */ 42383651Speter if (ntohs(req->r_rrq.rmp_session) != 42483651Speter ((rpl->r_type == RMP_BOOT_REPL)? ntohs(rpl->r_brpl.rmp_session): 4252997Swollman ntohs(rpl->r_rrpl.rmp_session))) { 42642957Sdillon syslog(LOG_ERR, "SendReadRepl: bad session id (%s)", 42742957Sdillon EnetStr(rconn)); 4281549Srgrimes rpl->r_rrpl.rmp_retcode = RMP_E_BADSID; 4291541Srgrimes retval = 1; 4301541Srgrimes goto sendpkt; 43138894Sbde } 43283651Speter 43338894Sbde /* 43438894Sbde * If the requester asks for more data than we can fit, 43538894Sbde * silently clamp the request size down to RMPREADDATA. 43683651Speter * 43783651Speter * N.B. I do not know if this is "legal", however it seems 43838894Sbde * to work. This is necessary for bpfwrite() on machines 43938894Sbde * with MCLBYTES less than 1514. 44038894Sbde */ 4411541Srgrimes if (ntohs(req->r_rrq.rmp_size) > RMPREADDATA) 4421541Srgrimes req->r_rrq.rmp_size = htons(RMPREADDATA); 4431541Srgrimes 4441541Srgrimes /* 4451541Srgrimes * Position read head on file according to info in request packet. 4461541Srgrimes */ 4471541Srgrimes GETWORD(req->r_rrq.rmp_offset, size); 4481541Srgrimes if (lseek(oldconn->bootfd, (off_t)size, SEEK_SET) < 0) { 4491541Srgrimes syslog(LOG_ERR, "SendReadRepl: lseek: %m (%s)", 4501541Srgrimes EnetStr(rconn)); 4511541Srgrimes rpl->r_rrpl.rmp_retcode = RMP_E_ABORT; 4521541Srgrimes retval = 1; 4531541Srgrimes goto sendpkt; 4541541Srgrimes } 4551549Srgrimes 45683651Speter /* 45783651Speter * Read data directly into reply packet. 4581541Srgrimes */ 45983651Speter if ((size = read(oldconn->bootfd, &rpl->r_rrpl.rmp_data, 46083651Speter (int) ntohs(req->r_rrq.rmp_size))) <= 0) { 46183651Speter if (size < 0) { 46283651Speter syslog(LOG_ERR, "SendReadRepl: read: %m (%s)", 46383651Speter EnetStr(rconn)); 4649336Sdfr rpl->r_rrpl.rmp_retcode = RMP_E_ABORT; 46584057Speter } else { 4661541Srgrimes rpl->r_rrpl.rmp_retcode = RMP_E_EOF; 4671541Srgrimes } 4681541Srgrimes retval = 1; 4691541Srgrimes goto sendpkt; 4709336Sdfr } 4711541Srgrimes 4721541Srgrimes /* 4739336Sdfr * Set success indication. 47484057Speter */ 47584057Speter rpl->r_rrpl.rmp_retcode = RMP_E_OKAY; 47684057Speter 4779336Sdfrsendpkt: 4789336Sdfr /* 4799336Sdfr * Set up assorted fields in reply packet. 4809336Sdfr */ 48148859Sphk rpl->r_rrpl.rmp_type = RMP_READ_REPL; 48216634Sbde COPYWORD(req->r_rrq.rmp_offset, rpl->r_rrpl.rmp_offset); 4839336Sdfr rpl->r_rrpl.rmp_session = req->r_rrq.rmp_session; 4841541Srgrimes 4859336Sdfr oldconn->rmplen = RMPREADSIZE(size); /* set size of packet */ 4869336Sdfr 4879336Sdfr retval &= SendPacket(oldconn); /* send packet */ 4889336Sdfr 4899336Sdfr if (madeconn) /* clean up after ourself */ 4909336Sdfr FreeConn(oldconn); 4919336Sdfr 4929336Sdfr return (retval); 4939336Sdfr} 4949336Sdfr 4959336Sdfr/* 4969336Sdfr** BootDone -- free up memory allocated for a connection. 4979336Sdfr** 4989336Sdfr** Parameters: 4999336Sdfr** rconn - incoming boot complete packet. 5009336Sdfr** 5019336Sdfr** Returns: 5029336Sdfr** 1 on success, 0 on failure. 5039336Sdfr** 5049336Sdfr** Side Effects: 5059336Sdfr** none. 5069336Sdfr*/ 5079336Sdfrint 50836541SpeterBootDone(RMPCONN *rconn) 5099336Sdfr{ 5109336Sdfr RMPCONN *oldconn; 5119336Sdfr struct rmp_packet *rpl; 5129336Sdfr 5139336Sdfr /* 5149336Sdfr * If we can't find the connection, ignore the request. 5159336Sdfr */ 5161541Srgrimes if ((oldconn = FindConn(rconn)) == NULL) { 5179336Sdfr syslog(LOG_ERR, "BootDone: no existing connection (%s)", 5181541Srgrimes EnetStr(rconn)); 5191541Srgrimes return(0); 5208876Srgrimes } 5211541Srgrimes 5221541Srgrimes rpl = &oldconn->rmp; /* cache ptr to RMP packet */ 5231541Srgrimes 5241541Srgrimes /* 5251541Srgrimes * Make sure Session ID's match. 52610219Sdfr */ 5279336Sdfr if (ntohs(rconn->rmp.r_rrq.rmp_session) != 5281541Srgrimes ((rpl->r_type == RMP_BOOT_REPL)? ntohs(rpl->r_brpl.rmp_session): 5291541Srgrimes ntohs(rpl->r_rrpl.rmp_session))) { 5301541Srgrimes syslog(LOG_ERR, "BootDone: bad session id (%s)", 5311541Srgrimes EnetStr(rconn)); 5321541Srgrimes return(0); 53363788Smckusick } 53463788Smckusick 5351541Srgrimes RemoveConn(oldconn); /* remove connection */ 53618397Snate 5371541Srgrimes syslog(LOG_INFO, "%s: boot complete", EnetStr(rconn)); 5381541Srgrimes 5391541Srgrimes return(1); 5401541Srgrimes} 54147028Sphk 5421541Srgrimes/* 5431541Srgrimes** SendPacket -- send an RMP packet to a remote host. 5449336Sdfr** 5459336Sdfr** Parameters: 5469336Sdfr** rconn - packet to be sent. 5479336Sdfr** 54847751Speter** Returns: 5499336Sdfr** 1 on success, 0 on failure. 55047751Speter** 55136541Speter** Side Effects: 55236541Speter** none. 5539336Sdfr*/ 5549336Sdfrint 5559336SdfrSendPacket(RMPCONN *rconn) 5569336Sdfr{ 5571541Srgrimes /* 5589336Sdfr * Set Ethernet Destination address to Source (BPF and the enet 5599336Sdfr * driver will take care of getting our source address set). 5609336Sdfr */ 56136541Speter memmove((char *)&rconn->rmp.hp_hdr.daddr[0], 56236541Speter (char *)&rconn->rmp.hp_hdr.saddr[0], RMP_ADDRLEN); 56347751Speter rconn->rmp.hp_hdr.len = htons(rconn->rmplen - sizeof(struct hp_hdr)); 56436541Speter 56536541Speter /* 5669336Sdfr * Reverse 802.2/HP Extended Source & Destination Access Pts. 5671541Srgrimes */ 56836541Speter rconn->rmp.hp_llc.dxsap = htons(HPEXT_SXSAP); 56936541Speter rconn->rmp.hp_llc.sxsap = htons(HPEXT_DXSAP); 57018397Snate 57183651Speter /* 5721541Srgrimes * Last time this connection was active. 5731541Srgrimes */ 57467486Sdwmalone (void)gettimeofday(&rconn->tstamp, NULL); 5751541Srgrimes 5761541Srgrimes if (DbgFp != NULL) /* display packet */ 57767486Sdwmalone DispPkt(rconn,DIR_SENT); 57867486Sdwmalone 57967486Sdwmalone /* 58067486Sdwmalone * Send RMP packet to remote host. 58167486Sdwmalone */ 58267486Sdwmalone return(BpfWrite(rconn)); 58367486Sdwmalone} 58467486Sdwmalone