rmpproto.c revision 27077
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: @(#)rmpproto.c 8.1 (Berkeley) 6/4/93 4227077Ssteve * $Id$ 431592Srgrimes * 4427074Ssteve * From: Utah Hdr: rmpproto.c 3.1 92/07/06 451592Srgrimes * Author: Jeff Forys, University of Utah CSS 461592Srgrimes */ 471592Srgrimes 481592Srgrimes#ifndef lint 4927077Sstevestatic const char sccsid[] = "@(#)rmpproto.c 8.1 (Berkeley) 6/4/93"; 501592Srgrimes#endif /* not lint */ 511592Srgrimes 521592Srgrimes#include <sys/param.h> 531592Srgrimes#include <sys/time.h> 541592Srgrimes 551592Srgrimes#include <errno.h> 561592Srgrimes#include <fcntl.h> 571592Srgrimes#include <stdio.h> 581592Srgrimes#include <string.h> 591592Srgrimes#include <syslog.h> 601592Srgrimes#include <unistd.h> 611592Srgrimes#include "defs.h" 621592Srgrimes 631592Srgrimes/* 641592Srgrimes** ProcessPacket -- determine packet type and do what's required. 651592Srgrimes** 661592Srgrimes** An RMP BOOT packet has been received. Look at the type field 671592Srgrimes** and process Boot Requests, Read Requests, and Boot Complete 681592Srgrimes** packets. Any other type will be dropped with a warning msg. 691592Srgrimes** 701592Srgrimes** Parameters: 711592Srgrimes** rconn - the new connection 721592Srgrimes** client - list of files available to this host 731592Srgrimes** 741592Srgrimes** Returns: 751592Srgrimes** Nothing. 761592Srgrimes** 771592Srgrimes** Side Effects: 781592Srgrimes** - If this is a valid boot request, it will be added to 791592Srgrimes** the linked list of outstanding requests (RmpConns). 801592Srgrimes** - If this is a valid boot complete, its associated 811592Srgrimes** entry in RmpConns will be deleted. 821592Srgrimes** - Also, unless we run out of memory, a reply will be 831592Srgrimes** sent to the host that sent the packet. 841592Srgrimes*/ 851592Srgrimesvoid 861592SrgrimesProcessPacket(rconn, client) 871592Srgrimes RMPCONN *rconn; 881592Srgrimes CLIENT *client; 891592Srgrimes{ 901592Srgrimes struct rmp_packet *rmp; 911592Srgrimes RMPCONN *rconnout; 921592Srgrimes 931592Srgrimes rmp = &rconn->rmp; /* cache pointer to RMP packet */ 941592Srgrimes 951592Srgrimes switch(rmp->r_type) { /* do what we came here to do */ 961592Srgrimes case RMP_BOOT_REQ: /* boot request */ 971592Srgrimes if ((rconnout = NewConn(rconn)) == NULL) 981592Srgrimes return; 991592Srgrimes 1001592Srgrimes /* 1011592Srgrimes * If the Session ID is 0xffff, this is a "probe" 1021592Srgrimes * packet and we do not want to add the connection 1031592Srgrimes * to the linked list of active connections. There 1041592Srgrimes * are two types of probe packets, if the Sequence 1051592Srgrimes * Number is 0 they want to know our host name, o/w 1061592Srgrimes * they want the name of the file associated with 1071592Srgrimes * the number spec'd by the Sequence Number. 1081592Srgrimes * 1091592Srgrimes * If this is an actual boot request, open the file 1101592Srgrimes * and send a reply. If SendBootRepl() does not 1111592Srgrimes * return 0, add the connection to the linked list 1121592Srgrimes * of active connections, otherwise delete it since 1131592Srgrimes * an error was encountered. 1141592Srgrimes */ 11527074Ssteve if (ntohs(rmp->r_brq.rmp_session) == RMP_PROBESID) { 1161592Srgrimes if (WORDZE(rmp->r_brq.rmp_seqno)) 1171592Srgrimes (void) SendServerID(rconnout); 1181592Srgrimes else 1191592Srgrimes (void) SendFileNo(rmp, rconnout, 1201592Srgrimes client? client->files: 1211592Srgrimes BootFiles); 1221592Srgrimes FreeConn(rconnout); 1231592Srgrimes } else { 1241592Srgrimes if (SendBootRepl(rmp, rconnout, 1251592Srgrimes client? client->files: BootFiles)) 1261592Srgrimes AddConn(rconnout); 1271592Srgrimes else 1281592Srgrimes FreeConn(rconnout); 1291592Srgrimes } 1301592Srgrimes break; 1311592Srgrimes 1321592Srgrimes case RMP_BOOT_REPL: /* boot reply (not valid) */ 1331592Srgrimes syslog(LOG_WARNING, "%s: sent a boot reply", 1341592Srgrimes EnetStr(rconn)); 1351592Srgrimes break; 1361592Srgrimes 1371592Srgrimes case RMP_READ_REQ: /* read request */ 1381592Srgrimes /* 1391592Srgrimes * Send a portion of the boot file. 1401592Srgrimes */ 1411592Srgrimes (void) SendReadRepl(rconn); 1421592Srgrimes break; 1431592Srgrimes 1441592Srgrimes case RMP_READ_REPL: /* read reply (not valid) */ 1451592Srgrimes syslog(LOG_WARNING, "%s: sent a read reply", 1461592Srgrimes EnetStr(rconn)); 1471592Srgrimes break; 1481592Srgrimes 1491592Srgrimes case RMP_BOOT_DONE: /* boot complete */ 1501592Srgrimes /* 1511592Srgrimes * Remove the entry from the linked list of active 1521592Srgrimes * connections. 1531592Srgrimes */ 1541592Srgrimes (void) BootDone(rconn); 1551592Srgrimes break; 1561592Srgrimes 1571592Srgrimes default: /* unknown RMP packet type */ 1581592Srgrimes syslog(LOG_WARNING, "%s: unknown packet type (%u)", 1591592Srgrimes EnetStr(rconn), rmp->r_type); 1601592Srgrimes } 1611592Srgrimes} 1621592Srgrimes 1631592Srgrimes/* 1641592Srgrimes** SendServerID -- send our host name to who ever requested it. 1651592Srgrimes** 1661592Srgrimes** Parameters: 1671592Srgrimes** rconn - the reply packet to be formatted. 1681592Srgrimes** 1691592Srgrimes** Returns: 1701592Srgrimes** 1 on success, 0 on failure. 1711592Srgrimes** 1721592Srgrimes** Side Effects: 1731592Srgrimes** none. 1741592Srgrimes*/ 1751592Srgrimesint 1761592SrgrimesSendServerID(rconn) 1771592Srgrimes RMPCONN *rconn; 1781592Srgrimes{ 1791592Srgrimes register struct rmp_packet *rpl; 1801592Srgrimes register char *src, *dst; 18127074Ssteve register u_int8_t *size; 1821592Srgrimes 1831592Srgrimes rpl = &rconn->rmp; /* cache ptr to RMP packet */ 1841592Srgrimes 1851592Srgrimes /* 1861592Srgrimes * Set up assorted fields in reply packet. 1871592Srgrimes */ 1881592Srgrimes rpl->r_brpl.rmp_type = RMP_BOOT_REPL; 1891592Srgrimes rpl->r_brpl.rmp_retcode = RMP_E_OKAY; 1901592Srgrimes ZEROWORD(rpl->r_brpl.rmp_seqno); 1911592Srgrimes rpl->r_brpl.rmp_session = 0; 19227074Ssteve rpl->r_brpl.rmp_version = htons(RMP_VERSION); 1931592Srgrimes 1941592Srgrimes size = &rpl->r_brpl.rmp_flnmsize; /* ptr to length of host name */ 1951592Srgrimes 1961592Srgrimes /* 1971592Srgrimes * Copy our host name into the reply packet incrementing the 1981592Srgrimes * length as we go. Stop at RMP_HOSTLEN or the first dot. 1991592Srgrimes */ 2001592Srgrimes src = MyHost; 2011592Srgrimes dst = (char *) &rpl->r_brpl.rmp_flnm; 2021592Srgrimes for (*size = 0; *size < RMP_HOSTLEN; (*size)++) { 2031592Srgrimes if (*src == '.' || *src == '\0') 2041592Srgrimes break; 2051592Srgrimes *dst++ = *src++; 2061592Srgrimes } 2071592Srgrimes 2081592Srgrimes rconn->rmplen = RMPBOOTSIZE(*size); /* set packet length */ 2091592Srgrimes 2101592Srgrimes return(SendPacket(rconn)); /* send packet */ 2111592Srgrimes} 2121592Srgrimes 2131592Srgrimes/* 2141592Srgrimes** SendFileNo -- send the name of a bootable file to the requester. 2151592Srgrimes** 2161592Srgrimes** Parameters: 2171592Srgrimes** req - RMP BOOT packet containing the request. 2181592Srgrimes** rconn - the reply packet to be formatted. 2191592Srgrimes** filelist - list of files available to the requester. 2201592Srgrimes** 2211592Srgrimes** Returns: 2221592Srgrimes** 1 on success, 0 on failure. 2231592Srgrimes** 2241592Srgrimes** Side Effects: 2251592Srgrimes** none. 2261592Srgrimes*/ 2271592Srgrimesint 2281592SrgrimesSendFileNo(req, rconn, filelist) 2291592Srgrimes struct rmp_packet *req; 2301592Srgrimes RMPCONN *rconn; 2311592Srgrimes char *filelist[]; 2321592Srgrimes{ 2331592Srgrimes register struct rmp_packet *rpl; 2341592Srgrimes register char *src, *dst; 23527074Ssteve register u_int8_t *size; 23627074Ssteve register int i; 2371592Srgrimes 2381592Srgrimes GETWORD(req->r_brpl.rmp_seqno, i); /* SeqNo is really FileNo */ 2391592Srgrimes rpl = &rconn->rmp; /* cache ptr to RMP packet */ 2401592Srgrimes 2411592Srgrimes /* 2421592Srgrimes * Set up assorted fields in reply packet. 2431592Srgrimes */ 2441592Srgrimes rpl->r_brpl.rmp_type = RMP_BOOT_REPL; 2451592Srgrimes PUTWORD(i, rpl->r_brpl.rmp_seqno); 2461592Srgrimes i--; 2471592Srgrimes rpl->r_brpl.rmp_session = 0; 24827074Ssteve rpl->r_brpl.rmp_version = htons(RMP_VERSION); 2491592Srgrimes 2501592Srgrimes size = &rpl->r_brpl.rmp_flnmsize; /* ptr to length of filename */ 2511592Srgrimes *size = 0; /* init length to zero */ 2521592Srgrimes 2531592Srgrimes /* 2541592Srgrimes * Copy the file name into the reply packet incrementing the 2551592Srgrimes * length as we go. Stop at end of string or when RMPBOOTDATA 2561592Srgrimes * characters have been copied. Also, set return code to 2571592Srgrimes * indicate success or "no more files". 2581592Srgrimes */ 2591592Srgrimes if (i < C_MAXFILE && filelist[i] != NULL) { 2601592Srgrimes src = filelist[i]; 2611592Srgrimes dst = (char *)&rpl->r_brpl.rmp_flnm; 2621592Srgrimes for (; *src && *size < RMPBOOTDATA; (*size)++) { 2631592Srgrimes if (*src == '\0') 2641592Srgrimes break; 2651592Srgrimes *dst++ = *src++; 2661592Srgrimes } 2671592Srgrimes rpl->r_brpl.rmp_retcode = RMP_E_OKAY; 2681592Srgrimes } else 2691592Srgrimes rpl->r_brpl.rmp_retcode = RMP_E_NODFLT; 2701592Srgrimes 2711592Srgrimes rconn->rmplen = RMPBOOTSIZE(*size); /* set packet length */ 2721592Srgrimes 2731592Srgrimes return(SendPacket(rconn)); /* send packet */ 2741592Srgrimes} 2751592Srgrimes 2761592Srgrimes/* 2771592Srgrimes** SendBootRepl -- open boot file and respond to boot request. 2781592Srgrimes** 2791592Srgrimes** Parameters: 2801592Srgrimes** req - RMP BOOT packet containing the request. 2811592Srgrimes** rconn - the reply packet to be formatted. 2821592Srgrimes** filelist - list of files available to the requester. 2831592Srgrimes** 2841592Srgrimes** Returns: 2851592Srgrimes** 1 on success, 0 on failure. 2861592Srgrimes** 2871592Srgrimes** Side Effects: 2881592Srgrimes** none. 2891592Srgrimes*/ 2901592Srgrimesint 2911592SrgrimesSendBootRepl(req, rconn, filelist) 2921592Srgrimes struct rmp_packet *req; 2931592Srgrimes RMPCONN *rconn; 2941592Srgrimes char *filelist[]; 2951592Srgrimes{ 2961592Srgrimes int retval; 2971592Srgrimes char *filename, filepath[RMPBOOTDATA+1]; 2981592Srgrimes RMPCONN *oldconn; 2991592Srgrimes register struct rmp_packet *rpl; 3001592Srgrimes register char *src, *dst1, *dst2; 30127074Ssteve register u_int8_t i; 3021592Srgrimes 3031592Srgrimes /* 3041592Srgrimes * If another connection already exists, delete it since we 3051592Srgrimes * are obviously starting again. 3061592Srgrimes */ 3071592Srgrimes if ((oldconn = FindConn(rconn)) != NULL) { 3081592Srgrimes syslog(LOG_WARNING, "%s: dropping existing connection", 3091592Srgrimes EnetStr(oldconn)); 3101592Srgrimes RemoveConn(oldconn); 3111592Srgrimes } 3121592Srgrimes 3131592Srgrimes rpl = &rconn->rmp; /* cache ptr to RMP packet */ 3141592Srgrimes 3151592Srgrimes /* 3161592Srgrimes * Set up assorted fields in reply packet. 3171592Srgrimes */ 3181592Srgrimes rpl->r_brpl.rmp_type = RMP_BOOT_REPL; 3191592Srgrimes COPYWORD(req->r_brq.rmp_seqno, rpl->r_brpl.rmp_seqno); 32027074Ssteve rpl->r_brpl.rmp_session = htons(GenSessID()); 32127074Ssteve rpl->r_brpl.rmp_version = htons(RMP_VERSION); 3221592Srgrimes rpl->r_brpl.rmp_flnmsize = req->r_brq.rmp_flnmsize; 3231592Srgrimes 3241592Srgrimes /* 3251592Srgrimes * Copy file name to `filepath' string, and into reply packet. 3261592Srgrimes */ 3271592Srgrimes src = &req->r_brq.rmp_flnm; 3281592Srgrimes dst1 = filepath; 3291592Srgrimes dst2 = &rpl->r_brpl.rmp_flnm; 3301592Srgrimes for (i = 0; i < req->r_brq.rmp_flnmsize; i++) 3311592Srgrimes *dst1++ = *dst2++ = *src++; 3321592Srgrimes *dst1 = '\0'; 3331592Srgrimes 3341592Srgrimes /* 3351592Srgrimes * If we are booting HP-UX machines, their secondary loader will 3361592Srgrimes * ask for files like "/hp-ux". As a security measure, we do not 3371592Srgrimes * allow boot files to lay outside the boot directory (unless they 3381592Srgrimes * are purposely link'd out. So, make `filename' become the path- 3391592Srgrimes * stripped file name and spoof the client into thinking that it 3401592Srgrimes * really got what it wanted. 3411592Srgrimes */ 3421592Srgrimes filename = (filename = rindex(filepath,'/'))? ++filename: filepath; 3431592Srgrimes 3441592Srgrimes /* 3451592Srgrimes * Check that this is a valid boot file name. 3461592Srgrimes */ 3471592Srgrimes for (i = 0; i < C_MAXFILE && filelist[i] != NULL; i++) 3481592Srgrimes if (STREQN(filename, filelist[i])) 3491592Srgrimes goto match; 3501592Srgrimes 3511592Srgrimes /* 3521592Srgrimes * Invalid boot file name, set error and send reply packet. 3531592Srgrimes */ 3541592Srgrimes rpl->r_brpl.rmp_retcode = RMP_E_NOFILE; 3551592Srgrimes retval = 0; 3561592Srgrimes goto sendpkt; 3571592Srgrimes 3581592Srgrimesmatch: 3591592Srgrimes /* 3601592Srgrimes * This is a valid boot file. Open the file and save the file 3611592Srgrimes * descriptor associated with this connection and set success 3621592Srgrimes * indication. If the file couldnt be opened, set error: 3631592Srgrimes * "no such file or dir" - RMP_E_NOFILE 3641592Srgrimes * "file table overflow" - RMP_E_BUSY 3651592Srgrimes * "too many open files" - RMP_E_BUSY 3661592Srgrimes * anything else - RMP_E_OPENFILE 3671592Srgrimes */ 3681592Srgrimes if ((rconn->bootfd = open(filename, O_RDONLY, 0600)) < 0) { 3691592Srgrimes rpl->r_brpl.rmp_retcode = (errno == ENOENT)? RMP_E_NOFILE: 3701592Srgrimes (errno == EMFILE || errno == ENFILE)? RMP_E_BUSY: 3711592Srgrimes RMP_E_OPENFILE; 3721592Srgrimes retval = 0; 3731592Srgrimes } else { 3741592Srgrimes rpl->r_brpl.rmp_retcode = RMP_E_OKAY; 3751592Srgrimes retval = 1; 3761592Srgrimes } 3771592Srgrimes 3781592Srgrimessendpkt: 3791592Srgrimes syslog(LOG_INFO, "%s: request to boot %s (%s)", 3801592Srgrimes EnetStr(rconn), filename, retval? "granted": "denied"); 3811592Srgrimes 3821592Srgrimes rconn->rmplen = RMPBOOTSIZE(rpl->r_brpl.rmp_flnmsize); 3831592Srgrimes 3841592Srgrimes return (retval & SendPacket(rconn)); 3851592Srgrimes} 3861592Srgrimes 3871592Srgrimes/* 3881592Srgrimes** SendReadRepl -- send a portion of the boot file to the requester. 3891592Srgrimes** 3901592Srgrimes** Parameters: 3911592Srgrimes** rconn - the reply packet to be formatted. 3921592Srgrimes** 3931592Srgrimes** Returns: 3941592Srgrimes** 1 on success, 0 on failure. 3951592Srgrimes** 3961592Srgrimes** Side Effects: 3971592Srgrimes** none. 3981592Srgrimes*/ 3991592Srgrimesint 4001592SrgrimesSendReadRepl(rconn) 4011592Srgrimes RMPCONN *rconn; 4021592Srgrimes{ 40327074Ssteve int retval = 0; 4041592Srgrimes RMPCONN *oldconn; 4051592Srgrimes register struct rmp_packet *rpl, *req; 4061592Srgrimes register int size = 0; 4071592Srgrimes int madeconn = 0; 4081592Srgrimes 4091592Srgrimes /* 4101592Srgrimes * Find the old connection. If one doesnt exist, create one only 4111592Srgrimes * to return the error code. 4121592Srgrimes */ 4131592Srgrimes if ((oldconn = FindConn(rconn)) == NULL) { 4141592Srgrimes if ((oldconn = NewConn(rconn)) == NULL) 4151592Srgrimes return(0); 4161592Srgrimes syslog(LOG_ERR, "SendReadRepl: no active connection (%s)", 4171592Srgrimes EnetStr(rconn)); 4181592Srgrimes madeconn++; 4191592Srgrimes } 4201592Srgrimes 4211592Srgrimes req = &rconn->rmp; /* cache ptr to request packet */ 4221592Srgrimes rpl = &oldconn->rmp; /* cache ptr to reply packet */ 4231592Srgrimes 4241592Srgrimes if (madeconn) { /* no active connection above; abort */ 4251592Srgrimes rpl->r_rrpl.rmp_retcode = RMP_E_ABORT; 4261592Srgrimes retval = 1; 4271592Srgrimes goto sendpkt; 4281592Srgrimes } 4291592Srgrimes 4301592Srgrimes /* 4311592Srgrimes * Make sure Session ID's match. 4321592Srgrimes */ 43327074Ssteve if (ntohs(req->r_rrq.rmp_session) != 43427074Ssteve ((rpl->r_type == RMP_BOOT_REPL)? ntohs(rpl->r_brpl.rmp_session): 43527074Ssteve ntohs(rpl->r_rrpl.rmp_session))) { 4361592Srgrimes syslog(LOG_ERR, "SendReadRepl: bad session id (%s)", 4371592Srgrimes EnetStr(rconn)); 4381592Srgrimes rpl->r_rrpl.rmp_retcode = RMP_E_BADSID; 4391592Srgrimes retval = 1; 4401592Srgrimes goto sendpkt; 4411592Srgrimes } 4421592Srgrimes 4431592Srgrimes /* 4441592Srgrimes * If the requester asks for more data than we can fit, 4451592Srgrimes * silently clamp the request size down to RMPREADDATA. 4461592Srgrimes * 4471592Srgrimes * N.B. I do not know if this is "legal", however it seems 4481592Srgrimes * to work. This is necessary for bpfwrite() on machines 4491592Srgrimes * with MCLBYTES less than 1514. 4501592Srgrimes */ 45127074Ssteve if (ntohs(req->r_rrq.rmp_size) > RMPREADDATA) 45227074Ssteve req->r_rrq.rmp_size = htons(RMPREADDATA); 4531592Srgrimes 4541592Srgrimes /* 4551592Srgrimes * Position read head on file according to info in request packet. 4561592Srgrimes */ 4571592Srgrimes GETWORD(req->r_rrq.rmp_offset, size); 4581592Srgrimes if (lseek(oldconn->bootfd, (off_t)size, L_SET) < 0) { 4591592Srgrimes syslog(LOG_ERR, "SendReadRepl: lseek: %m (%s)", 4601592Srgrimes EnetStr(rconn)); 4611592Srgrimes rpl->r_rrpl.rmp_retcode = RMP_E_ABORT; 4621592Srgrimes retval = 1; 4631592Srgrimes goto sendpkt; 4641592Srgrimes } 4651592Srgrimes 4661592Srgrimes /* 4671592Srgrimes * Read data directly into reply packet. 4681592Srgrimes */ 4691592Srgrimes if ((size = read(oldconn->bootfd, &rpl->r_rrpl.rmp_data, 47027074Ssteve (int) ntohs(req->r_rrq.rmp_size))) <= 0) { 4711592Srgrimes if (size < 0) { 4721592Srgrimes syslog(LOG_ERR, "SendReadRepl: read: %m (%s)", 4731592Srgrimes EnetStr(rconn)); 4741592Srgrimes rpl->r_rrpl.rmp_retcode = RMP_E_ABORT; 4751592Srgrimes } else { 4761592Srgrimes rpl->r_rrpl.rmp_retcode = RMP_E_EOF; 4771592Srgrimes } 4781592Srgrimes retval = 1; 4791592Srgrimes goto sendpkt; 4801592Srgrimes } 4811592Srgrimes 4821592Srgrimes /* 4831592Srgrimes * Set success indication. 4841592Srgrimes */ 4851592Srgrimes rpl->r_rrpl.rmp_retcode = RMP_E_OKAY; 4861592Srgrimes 4871592Srgrimessendpkt: 4881592Srgrimes /* 4891592Srgrimes * Set up assorted fields in reply packet. 4901592Srgrimes */ 4911592Srgrimes rpl->r_rrpl.rmp_type = RMP_READ_REPL; 4921592Srgrimes COPYWORD(req->r_rrq.rmp_offset, rpl->r_rrpl.rmp_offset); 4931592Srgrimes rpl->r_rrpl.rmp_session = req->r_rrq.rmp_session; 4941592Srgrimes 4951592Srgrimes oldconn->rmplen = RMPREADSIZE(size); /* set size of packet */ 4961592Srgrimes 4971592Srgrimes retval &= SendPacket(oldconn); /* send packet */ 4981592Srgrimes 4991592Srgrimes if (madeconn) /* clean up after ourself */ 5001592Srgrimes FreeConn(oldconn); 5011592Srgrimes 5021592Srgrimes return (retval); 5031592Srgrimes} 5041592Srgrimes 5051592Srgrimes/* 5061592Srgrimes** BootDone -- free up memory allocated for a connection. 5071592Srgrimes** 5081592Srgrimes** Parameters: 5091592Srgrimes** rconn - incoming boot complete packet. 5101592Srgrimes** 5111592Srgrimes** Returns: 5121592Srgrimes** 1 on success, 0 on failure. 5131592Srgrimes** 5141592Srgrimes** Side Effects: 5151592Srgrimes** none. 5161592Srgrimes*/ 5171592Srgrimesint 5181592SrgrimesBootDone(rconn) 5191592Srgrimes RMPCONN *rconn; 5201592Srgrimes{ 5211592Srgrimes RMPCONN *oldconn; 5221592Srgrimes struct rmp_packet *rpl; 5231592Srgrimes 5241592Srgrimes /* 5251592Srgrimes * If we cant find the connection, ignore the request. 5261592Srgrimes */ 5271592Srgrimes if ((oldconn = FindConn(rconn)) == NULL) { 5281592Srgrimes syslog(LOG_ERR, "BootDone: no existing connection (%s)", 5291592Srgrimes EnetStr(rconn)); 5301592Srgrimes return(0); 5311592Srgrimes } 5321592Srgrimes 5331592Srgrimes rpl = &oldconn->rmp; /* cache ptr to RMP packet */ 5341592Srgrimes 5351592Srgrimes /* 5361592Srgrimes * Make sure Session ID's match. 5371592Srgrimes */ 53827074Ssteve if (ntohs(rconn->rmp.r_rrq.rmp_session) != 53927074Ssteve ((rpl->r_type == RMP_BOOT_REPL)? ntohs(rpl->r_brpl.rmp_session): 54027074Ssteve ntohs(rpl->r_rrpl.rmp_session))) { 5411592Srgrimes syslog(LOG_ERR, "BootDone: bad session id (%s)", 5421592Srgrimes EnetStr(rconn)); 5431592Srgrimes return(0); 5441592Srgrimes } 5451592Srgrimes 5461592Srgrimes RemoveConn(oldconn); /* remove connection */ 5471592Srgrimes 5481592Srgrimes syslog(LOG_INFO, "%s: boot complete", EnetStr(rconn)); 5491592Srgrimes 5501592Srgrimes return(1); 5511592Srgrimes} 5521592Srgrimes 5531592Srgrimes/* 5541592Srgrimes** SendPacket -- send an RMP packet to a remote host. 5551592Srgrimes** 5561592Srgrimes** Parameters: 5571592Srgrimes** rconn - packet to be sent. 5581592Srgrimes** 5591592Srgrimes** Returns: 5601592Srgrimes** 1 on success, 0 on failure. 5611592Srgrimes** 5621592Srgrimes** Side Effects: 5631592Srgrimes** none. 5641592Srgrimes*/ 5651592Srgrimesint 5661592SrgrimesSendPacket(rconn) 5671592Srgrimes register RMPCONN *rconn; 5681592Srgrimes{ 5691592Srgrimes /* 5701592Srgrimes * Set Ethernet Destination address to Source (BPF and the enet 5711592Srgrimes * driver will take care of getting our source address set). 5721592Srgrimes */ 5731592Srgrimes bcopy((char *)&rconn->rmp.hp_hdr.saddr[0], 5741592Srgrimes (char *)&rconn->rmp.hp_hdr.daddr[0], RMP_ADDRLEN); 57527074Ssteve#ifdef __FreeBSD__ 57627074Ssteve /* BPF (incorrectly) wants this in host order. */ 5771592Srgrimes rconn->rmp.hp_hdr.len = rconn->rmplen - sizeof(struct hp_hdr); 57827074Ssteve#else 57927074Ssteve rconn->rmp.hp_hdr.len = htons(rconn->rmplen - sizeof(struct hp_hdr)); 58027074Ssteve#endif 5811592Srgrimes 5821592Srgrimes /* 5831592Srgrimes * Reverse 802.2/HP Extended Source & Destination Access Pts. 5841592Srgrimes */ 58527074Ssteve rconn->rmp.hp_llc.dxsap = htons(HPEXT_SXSAP); 58627074Ssteve rconn->rmp.hp_llc.sxsap = htons(HPEXT_DXSAP); 5871592Srgrimes 5881592Srgrimes /* 5891592Srgrimes * Last time this connection was active. 5901592Srgrimes */ 5911592Srgrimes (void) gettimeofday(&rconn->tstamp, (struct timezone *)0); 5921592Srgrimes 5931592Srgrimes if (DbgFp != NULL) /* display packet */ 5941592Srgrimes DispPkt(rconn,DIR_SENT); 5951592Srgrimes 5961592Srgrimes /* 5971592Srgrimes * Send RMP packet to remote host. 5981592Srgrimes */ 5991592Srgrimes return(BpfWrite(rconn)); 6001592Srgrimes} 601