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. 21262435Sbrueffer * 3. Neither the name of the University nor the names of its contributors 221592Srgrimes * may be used to endorse or promote products derived from this software 231592Srgrimes * without specific prior written permission. 241592Srgrimes * 251592Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 261592Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 271592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 281592Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 291592Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 301592Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 311592Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 321592Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 331592Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 341592Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 351592Srgrimes * SUCH DAMAGE. 361592Srgrimes * 3727074Ssteve * from: @(#)rmpproto.c 8.1 (Berkeley) 6/4/93 381592Srgrimes * 3927074Ssteve * From: Utah Hdr: rmpproto.c 3.1 92/07/06 401592Srgrimes * Author: Jeff Forys, University of Utah CSS 411592Srgrimes */ 421592Srgrimes 431592Srgrimes#ifndef lint 4431386Scharnier#if 0 4527077Sstevestatic const char sccsid[] = "@(#)rmpproto.c 8.1 (Berkeley) 6/4/93"; 4631386Scharnier#endif 4731386Scharnierstatic const char rcsid[] = 4850476Speter "$FreeBSD: stable/10/libexec/rbootd/rmpproto.c 357517 2020-02-04 19:19:48Z dim $"; 491592Srgrimes#endif /* not lint */ 501592Srgrimes 511592Srgrimes#include <sys/param.h> 521592Srgrimes#include <sys/time.h> 53129652Sstefanf#include <netinet/in.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 8690377SimpProcessPacket(RMPCONN *rconn, CLIENT *client) 871592Srgrimes{ 881592Srgrimes struct rmp_packet *rmp; 891592Srgrimes RMPCONN *rconnout; 901592Srgrimes 911592Srgrimes rmp = &rconn->rmp; /* cache pointer to RMP packet */ 921592Srgrimes 931592Srgrimes switch(rmp->r_type) { /* do what we came here to do */ 941592Srgrimes case RMP_BOOT_REQ: /* boot request */ 951592Srgrimes if ((rconnout = NewConn(rconn)) == NULL) 961592Srgrimes return; 971592Srgrimes 981592Srgrimes /* 991592Srgrimes * If the Session ID is 0xffff, this is a "probe" 1001592Srgrimes * packet and we do not want to add the connection 1011592Srgrimes * to the linked list of active connections. There 1021592Srgrimes * are two types of probe packets, if the Sequence 1031592Srgrimes * Number is 0 they want to know our host name, o/w 1041592Srgrimes * they want the name of the file associated with 1051592Srgrimes * the number spec'd by the Sequence Number. 1061592Srgrimes * 1071592Srgrimes * If this is an actual boot request, open the file 1081592Srgrimes * and send a reply. If SendBootRepl() does not 1091592Srgrimes * return 0, add the connection to the linked list 1101592Srgrimes * of active connections, otherwise delete it since 1111592Srgrimes * an error was encountered. 1121592Srgrimes */ 11327074Ssteve if (ntohs(rmp->r_brq.rmp_session) == RMP_PROBESID) { 1141592Srgrimes if (WORDZE(rmp->r_brq.rmp_seqno)) 1151592Srgrimes (void) SendServerID(rconnout); 1161592Srgrimes else 1171592Srgrimes (void) SendFileNo(rmp, rconnout, 1181592Srgrimes client? client->files: 1191592Srgrimes BootFiles); 1201592Srgrimes FreeConn(rconnout); 1211592Srgrimes } else { 1221592Srgrimes if (SendBootRepl(rmp, rconnout, 1231592Srgrimes client? client->files: BootFiles)) 1241592Srgrimes AddConn(rconnout); 1251592Srgrimes else 1261592Srgrimes FreeConn(rconnout); 1271592Srgrimes } 1281592Srgrimes break; 1291592Srgrimes 1301592Srgrimes case RMP_BOOT_REPL: /* boot reply (not valid) */ 1311592Srgrimes syslog(LOG_WARNING, "%s: sent a boot reply", 1321592Srgrimes EnetStr(rconn)); 1331592Srgrimes break; 1341592Srgrimes 1351592Srgrimes case RMP_READ_REQ: /* read request */ 1361592Srgrimes /* 1371592Srgrimes * Send a portion of the boot file. 1381592Srgrimes */ 1391592Srgrimes (void) SendReadRepl(rconn); 1401592Srgrimes break; 1411592Srgrimes 1421592Srgrimes case RMP_READ_REPL: /* read reply (not valid) */ 1431592Srgrimes syslog(LOG_WARNING, "%s: sent a read reply", 1441592Srgrimes EnetStr(rconn)); 1451592Srgrimes break; 1461592Srgrimes 1471592Srgrimes case RMP_BOOT_DONE: /* boot complete */ 1481592Srgrimes /* 1491592Srgrimes * Remove the entry from the linked list of active 1501592Srgrimes * connections. 1511592Srgrimes */ 1521592Srgrimes (void) BootDone(rconn); 1531592Srgrimes break; 1541592Srgrimes 1551592Srgrimes default: /* unknown RMP packet type */ 1561592Srgrimes syslog(LOG_WARNING, "%s: unknown packet type (%u)", 1571592Srgrimes EnetStr(rconn), rmp->r_type); 1581592Srgrimes } 1591592Srgrimes} 1601592Srgrimes 1611592Srgrimes/* 1621592Srgrimes** SendServerID -- send our host name to who ever requested it. 1631592Srgrimes** 1641592Srgrimes** Parameters: 1651592Srgrimes** rconn - the reply packet to be formatted. 1661592Srgrimes** 1671592Srgrimes** Returns: 1681592Srgrimes** 1 on success, 0 on failure. 1691592Srgrimes** 1701592Srgrimes** Side Effects: 1711592Srgrimes** none. 1721592Srgrimes*/ 1731592Srgrimesint 17490377SimpSendServerID(RMPCONN *rconn) 1751592Srgrimes{ 17627079Ssteve struct rmp_packet *rpl; 17727079Ssteve char *src, *dst; 17827079Ssteve u_int8_t *size; 1791592Srgrimes 1801592Srgrimes rpl = &rconn->rmp; /* cache ptr to RMP packet */ 1811592Srgrimes 1821592Srgrimes /* 1831592Srgrimes * Set up assorted fields in reply packet. 1841592Srgrimes */ 1851592Srgrimes rpl->r_brpl.rmp_type = RMP_BOOT_REPL; 1861592Srgrimes rpl->r_brpl.rmp_retcode = RMP_E_OKAY; 1871592Srgrimes ZEROWORD(rpl->r_brpl.rmp_seqno); 1881592Srgrimes rpl->r_brpl.rmp_session = 0; 18927074Ssteve rpl->r_brpl.rmp_version = htons(RMP_VERSION); 1901592Srgrimes 1911592Srgrimes size = &rpl->r_brpl.rmp_flnmsize; /* ptr to length of host name */ 1921592Srgrimes 1931592Srgrimes /* 1941592Srgrimes * Copy our host name into the reply packet incrementing the 1951592Srgrimes * length as we go. Stop at RMP_HOSTLEN or the first dot. 1961592Srgrimes */ 1971592Srgrimes src = MyHost; 1981592Srgrimes dst = (char *) &rpl->r_brpl.rmp_flnm; 1991592Srgrimes for (*size = 0; *size < RMP_HOSTLEN; (*size)++) { 2001592Srgrimes if (*src == '.' || *src == '\0') 2011592Srgrimes break; 2021592Srgrimes *dst++ = *src++; 2031592Srgrimes } 2041592Srgrimes 2051592Srgrimes rconn->rmplen = RMPBOOTSIZE(*size); /* set packet length */ 2061592Srgrimes 2071592Srgrimes return(SendPacket(rconn)); /* send packet */ 2081592Srgrimes} 2091592Srgrimes 2101592Srgrimes/* 2111592Srgrimes** SendFileNo -- send the name of a bootable file to the requester. 2121592Srgrimes** 2131592Srgrimes** Parameters: 2141592Srgrimes** req - RMP BOOT packet containing the request. 2151592Srgrimes** rconn - the reply packet to be formatted. 2161592Srgrimes** filelist - list of files available to the requester. 2171592Srgrimes** 2181592Srgrimes** Returns: 2191592Srgrimes** 1 on success, 0 on failure. 2201592Srgrimes** 2211592Srgrimes** Side Effects: 2221592Srgrimes** none. 2231592Srgrimes*/ 2241592Srgrimesint 22590377SimpSendFileNo(struct rmp_packet *req, RMPCONN *rconn, char *filelist[]) 2261592Srgrimes{ 22727079Ssteve struct rmp_packet *rpl; 22827079Ssteve char *src, *dst; 22927079Ssteve u_int8_t *size; 23027079Ssteve int i; 2311592Srgrimes 2321592Srgrimes GETWORD(req->r_brpl.rmp_seqno, i); /* SeqNo is really FileNo */ 2331592Srgrimes rpl = &rconn->rmp; /* cache ptr to RMP packet */ 2341592Srgrimes 2351592Srgrimes /* 2361592Srgrimes * Set up assorted fields in reply packet. 2371592Srgrimes */ 2381592Srgrimes rpl->r_brpl.rmp_type = RMP_BOOT_REPL; 2391592Srgrimes PUTWORD(i, rpl->r_brpl.rmp_seqno); 2401592Srgrimes i--; 2411592Srgrimes rpl->r_brpl.rmp_session = 0; 24227074Ssteve rpl->r_brpl.rmp_version = htons(RMP_VERSION); 2431592Srgrimes 2441592Srgrimes size = &rpl->r_brpl.rmp_flnmsize; /* ptr to length of filename */ 2451592Srgrimes *size = 0; /* init length to zero */ 2461592Srgrimes 2471592Srgrimes /* 2481592Srgrimes * Copy the file name into the reply packet incrementing the 2491592Srgrimes * length as we go. Stop at end of string or when RMPBOOTDATA 2501592Srgrimes * characters have been copied. Also, set return code to 2511592Srgrimes * indicate success or "no more files". 2521592Srgrimes */ 2531592Srgrimes if (i < C_MAXFILE && filelist[i] != NULL) { 2541592Srgrimes src = filelist[i]; 2551592Srgrimes dst = (char *)&rpl->r_brpl.rmp_flnm; 2561592Srgrimes for (; *src && *size < RMPBOOTDATA; (*size)++) { 2571592Srgrimes if (*src == '\0') 2581592Srgrimes break; 2591592Srgrimes *dst++ = *src++; 2601592Srgrimes } 2611592Srgrimes rpl->r_brpl.rmp_retcode = RMP_E_OKAY; 2621592Srgrimes } else 2631592Srgrimes rpl->r_brpl.rmp_retcode = RMP_E_NODFLT; 2641592Srgrimes 2651592Srgrimes rconn->rmplen = RMPBOOTSIZE(*size); /* set packet length */ 2661592Srgrimes 2671592Srgrimes return(SendPacket(rconn)); /* send packet */ 2681592Srgrimes} 2691592Srgrimes 2701592Srgrimes/* 2711592Srgrimes** SendBootRepl -- open boot file and respond to boot request. 2721592Srgrimes** 2731592Srgrimes** Parameters: 2741592Srgrimes** req - RMP BOOT packet containing the request. 2751592Srgrimes** rconn - the reply packet to be formatted. 2761592Srgrimes** filelist - list of files available to the requester. 2771592Srgrimes** 2781592Srgrimes** Returns: 2791592Srgrimes** 1 on success, 0 on failure. 2801592Srgrimes** 2811592Srgrimes** Side Effects: 2821592Srgrimes** none. 2831592Srgrimes*/ 2841592Srgrimesint 28590377SimpSendBootRepl(struct rmp_packet *req, RMPCONN *rconn, char *filelist[]) 2861592Srgrimes{ 2871592Srgrimes int retval; 2881592Srgrimes char *filename, filepath[RMPBOOTDATA+1]; 2891592Srgrimes RMPCONN *oldconn; 29027079Ssteve struct rmp_packet *rpl; 29127079Ssteve char *src, *dst1, *dst2; 29227079Ssteve u_int8_t i; 2931592Srgrimes 2941592Srgrimes /* 2951592Srgrimes * If another connection already exists, delete it since we 2961592Srgrimes * are obviously starting again. 2971592Srgrimes */ 2981592Srgrimes if ((oldconn = FindConn(rconn)) != NULL) { 2991592Srgrimes syslog(LOG_WARNING, "%s: dropping existing connection", 3001592Srgrimes EnetStr(oldconn)); 3011592Srgrimes RemoveConn(oldconn); 3021592Srgrimes } 3031592Srgrimes 3041592Srgrimes rpl = &rconn->rmp; /* cache ptr to RMP packet */ 3051592Srgrimes 3061592Srgrimes /* 3071592Srgrimes * Set up assorted fields in reply packet. 3081592Srgrimes */ 3091592Srgrimes rpl->r_brpl.rmp_type = RMP_BOOT_REPL; 3101592Srgrimes COPYWORD(req->r_brq.rmp_seqno, rpl->r_brpl.rmp_seqno); 31127074Ssteve rpl->r_brpl.rmp_session = htons(GenSessID()); 31227074Ssteve rpl->r_brpl.rmp_version = htons(RMP_VERSION); 3131592Srgrimes rpl->r_brpl.rmp_flnmsize = req->r_brq.rmp_flnmsize; 3141592Srgrimes 3151592Srgrimes /* 3161592Srgrimes * Copy file name to `filepath' string, and into reply packet. 3171592Srgrimes */ 3181592Srgrimes src = &req->r_brq.rmp_flnm; 3191592Srgrimes dst1 = filepath; 3201592Srgrimes dst2 = &rpl->r_brpl.rmp_flnm; 3211592Srgrimes for (i = 0; i < req->r_brq.rmp_flnmsize; i++) 3221592Srgrimes *dst1++ = *dst2++ = *src++; 3231592Srgrimes *dst1 = '\0'; 3241592Srgrimes 3251592Srgrimes /* 3261592Srgrimes * If we are booting HP-UX machines, their secondary loader will 3271592Srgrimes * ask for files like "/hp-ux". As a security measure, we do not 3281592Srgrimes * allow boot files to lay outside the boot directory (unless they 3291592Srgrimes * are purposely link'd out. So, make `filename' become the path- 3301592Srgrimes * stripped file name and spoof the client into thinking that it 3311592Srgrimes * really got what it wanted. 3321592Srgrimes */ 333357517Sdim filename = strrchr(filepath,'/'); 334357517Sdim filename = filename? filename + 1: filepath; 3351592Srgrimes 3361592Srgrimes /* 3371592Srgrimes * Check that this is a valid boot file name. 3381592Srgrimes */ 3391592Srgrimes for (i = 0; i < C_MAXFILE && filelist[i] != NULL; i++) 3401592Srgrimes if (STREQN(filename, filelist[i])) 3411592Srgrimes goto match; 3421592Srgrimes 3431592Srgrimes /* 3441592Srgrimes * Invalid boot file name, set error and send reply packet. 3451592Srgrimes */ 3461592Srgrimes rpl->r_brpl.rmp_retcode = RMP_E_NOFILE; 3471592Srgrimes retval = 0; 3481592Srgrimes goto sendpkt; 3491592Srgrimes 3501592Srgrimesmatch: 3511592Srgrimes /* 3521592Srgrimes * This is a valid boot file. Open the file and save the file 3531592Srgrimes * descriptor associated with this connection and set success 3541592Srgrimes * indication. If the file couldnt be opened, set error: 3551592Srgrimes * "no such file or dir" - RMP_E_NOFILE 3561592Srgrimes * "file table overflow" - RMP_E_BUSY 3571592Srgrimes * "too many open files" - RMP_E_BUSY 3581592Srgrimes * anything else - RMP_E_OPENFILE 3591592Srgrimes */ 3601592Srgrimes if ((rconn->bootfd = open(filename, O_RDONLY, 0600)) < 0) { 3611592Srgrimes rpl->r_brpl.rmp_retcode = (errno == ENOENT)? RMP_E_NOFILE: 3621592Srgrimes (errno == EMFILE || errno == ENFILE)? RMP_E_BUSY: 3631592Srgrimes RMP_E_OPENFILE; 3641592Srgrimes retval = 0; 3651592Srgrimes } else { 3661592Srgrimes rpl->r_brpl.rmp_retcode = RMP_E_OKAY; 3671592Srgrimes retval = 1; 3681592Srgrimes } 3691592Srgrimes 3701592Srgrimessendpkt: 3711592Srgrimes syslog(LOG_INFO, "%s: request to boot %s (%s)", 3721592Srgrimes EnetStr(rconn), filename, retval? "granted": "denied"); 3731592Srgrimes 3741592Srgrimes rconn->rmplen = RMPBOOTSIZE(rpl->r_brpl.rmp_flnmsize); 3751592Srgrimes 3761592Srgrimes return (retval & SendPacket(rconn)); 3771592Srgrimes} 3781592Srgrimes 3791592Srgrimes/* 3801592Srgrimes** SendReadRepl -- send a portion of the boot file to the requester. 3811592Srgrimes** 3821592Srgrimes** Parameters: 3831592Srgrimes** rconn - the reply packet to be formatted. 3841592Srgrimes** 3851592Srgrimes** Returns: 3861592Srgrimes** 1 on success, 0 on failure. 3871592Srgrimes** 3881592Srgrimes** Side Effects: 3891592Srgrimes** none. 3901592Srgrimes*/ 3911592Srgrimesint 39290377SimpSendReadRepl(RMPCONN *rconn) 3931592Srgrimes{ 39427074Ssteve int retval = 0; 3951592Srgrimes RMPCONN *oldconn; 39627079Ssteve struct rmp_packet *rpl, *req; 39727079Ssteve int size = 0; 3981592Srgrimes int madeconn = 0; 3991592Srgrimes 4001592Srgrimes /* 401229780Suqs * Find the old connection. If one doesn't exist, create one only 4021592Srgrimes * to return the error code. 4031592Srgrimes */ 4041592Srgrimes if ((oldconn = FindConn(rconn)) == NULL) { 4051592Srgrimes if ((oldconn = NewConn(rconn)) == NULL) 4061592Srgrimes return(0); 4071592Srgrimes syslog(LOG_ERR, "SendReadRepl: no active connection (%s)", 4081592Srgrimes EnetStr(rconn)); 4091592Srgrimes madeconn++; 4101592Srgrimes } 4111592Srgrimes 4121592Srgrimes req = &rconn->rmp; /* cache ptr to request packet */ 4131592Srgrimes rpl = &oldconn->rmp; /* cache ptr to reply packet */ 4141592Srgrimes 4151592Srgrimes if (madeconn) { /* no active connection above; abort */ 4161592Srgrimes rpl->r_rrpl.rmp_retcode = RMP_E_ABORT; 4171592Srgrimes retval = 1; 4181592Srgrimes goto sendpkt; 4191592Srgrimes } 4201592Srgrimes 4211592Srgrimes /* 4221592Srgrimes * Make sure Session ID's match. 4231592Srgrimes */ 42427074Ssteve if (ntohs(req->r_rrq.rmp_session) != 42527074Ssteve ((rpl->r_type == RMP_BOOT_REPL)? ntohs(rpl->r_brpl.rmp_session): 42627074Ssteve ntohs(rpl->r_rrpl.rmp_session))) { 4271592Srgrimes syslog(LOG_ERR, "SendReadRepl: bad session id (%s)", 4281592Srgrimes EnetStr(rconn)); 4291592Srgrimes rpl->r_rrpl.rmp_retcode = RMP_E_BADSID; 4301592Srgrimes retval = 1; 4311592Srgrimes goto sendpkt; 4321592Srgrimes } 4331592Srgrimes 4341592Srgrimes /* 4351592Srgrimes * If the requester asks for more data than we can fit, 4361592Srgrimes * silently clamp the request size down to RMPREADDATA. 4371592Srgrimes * 4381592Srgrimes * N.B. I do not know if this is "legal", however it seems 4391592Srgrimes * to work. This is necessary for bpfwrite() on machines 4401592Srgrimes * with MCLBYTES less than 1514. 4411592Srgrimes */ 44227074Ssteve if (ntohs(req->r_rrq.rmp_size) > RMPREADDATA) 44327074Ssteve req->r_rrq.rmp_size = htons(RMPREADDATA); 4441592Srgrimes 4451592Srgrimes /* 4461592Srgrimes * Position read head on file according to info in request packet. 4471592Srgrimes */ 4481592Srgrimes GETWORD(req->r_rrq.rmp_offset, size); 44968895Skris if (lseek(oldconn->bootfd, (off_t)size, SEEK_SET) < 0) { 4501592Srgrimes syslog(LOG_ERR, "SendReadRepl: lseek: %m (%s)", 4511592Srgrimes EnetStr(rconn)); 4521592Srgrimes rpl->r_rrpl.rmp_retcode = RMP_E_ABORT; 4531592Srgrimes retval = 1; 4541592Srgrimes goto sendpkt; 4551592Srgrimes } 4561592Srgrimes 4571592Srgrimes /* 4581592Srgrimes * Read data directly into reply packet. 4591592Srgrimes */ 4601592Srgrimes if ((size = read(oldconn->bootfd, &rpl->r_rrpl.rmp_data, 46127074Ssteve (int) ntohs(req->r_rrq.rmp_size))) <= 0) { 4621592Srgrimes if (size < 0) { 4631592Srgrimes syslog(LOG_ERR, "SendReadRepl: read: %m (%s)", 4641592Srgrimes EnetStr(rconn)); 4651592Srgrimes rpl->r_rrpl.rmp_retcode = RMP_E_ABORT; 4661592Srgrimes } else { 4671592Srgrimes rpl->r_rrpl.rmp_retcode = RMP_E_EOF; 4681592Srgrimes } 4691592Srgrimes retval = 1; 4701592Srgrimes goto sendpkt; 4711592Srgrimes } 4721592Srgrimes 4731592Srgrimes /* 4741592Srgrimes * Set success indication. 4751592Srgrimes */ 4761592Srgrimes rpl->r_rrpl.rmp_retcode = RMP_E_OKAY; 4771592Srgrimes 4781592Srgrimessendpkt: 4791592Srgrimes /* 4801592Srgrimes * Set up assorted fields in reply packet. 4811592Srgrimes */ 4821592Srgrimes rpl->r_rrpl.rmp_type = RMP_READ_REPL; 4831592Srgrimes COPYWORD(req->r_rrq.rmp_offset, rpl->r_rrpl.rmp_offset); 4841592Srgrimes rpl->r_rrpl.rmp_session = req->r_rrq.rmp_session; 4851592Srgrimes 4861592Srgrimes oldconn->rmplen = RMPREADSIZE(size); /* set size of packet */ 4871592Srgrimes 4881592Srgrimes retval &= SendPacket(oldconn); /* send packet */ 4891592Srgrimes 4901592Srgrimes if (madeconn) /* clean up after ourself */ 4911592Srgrimes FreeConn(oldconn); 4921592Srgrimes 4931592Srgrimes return (retval); 4941592Srgrimes} 4951592Srgrimes 4961592Srgrimes/* 4971592Srgrimes** BootDone -- free up memory allocated for a connection. 4981592Srgrimes** 4991592Srgrimes** Parameters: 5001592Srgrimes** rconn - incoming boot complete packet. 5011592Srgrimes** 5021592Srgrimes** Returns: 5031592Srgrimes** 1 on success, 0 on failure. 5041592Srgrimes** 5051592Srgrimes** Side Effects: 5061592Srgrimes** none. 5071592Srgrimes*/ 5081592Srgrimesint 50990377SimpBootDone(RMPCONN *rconn) 5101592Srgrimes{ 5111592Srgrimes RMPCONN *oldconn; 5121592Srgrimes struct rmp_packet *rpl; 5131592Srgrimes 5141592Srgrimes /* 515229780Suqs * If we can't find the connection, ignore the request. 5161592Srgrimes */ 5171592Srgrimes if ((oldconn = FindConn(rconn)) == NULL) { 5181592Srgrimes syslog(LOG_ERR, "BootDone: no existing connection (%s)", 5191592Srgrimes EnetStr(rconn)); 5201592Srgrimes return(0); 5211592Srgrimes } 5221592Srgrimes 5231592Srgrimes rpl = &oldconn->rmp; /* cache ptr to RMP packet */ 5241592Srgrimes 5251592Srgrimes /* 5261592Srgrimes * Make sure Session ID's match. 5271592Srgrimes */ 52827074Ssteve if (ntohs(rconn->rmp.r_rrq.rmp_session) != 52927074Ssteve ((rpl->r_type == RMP_BOOT_REPL)? ntohs(rpl->r_brpl.rmp_session): 53027074Ssteve ntohs(rpl->r_rrpl.rmp_session))) { 5311592Srgrimes syslog(LOG_ERR, "BootDone: bad session id (%s)", 5321592Srgrimes EnetStr(rconn)); 5331592Srgrimes return(0); 5341592Srgrimes } 5351592Srgrimes 5361592Srgrimes RemoveConn(oldconn); /* remove connection */ 5371592Srgrimes 5381592Srgrimes syslog(LOG_INFO, "%s: boot complete", EnetStr(rconn)); 5391592Srgrimes 5401592Srgrimes return(1); 5411592Srgrimes} 5421592Srgrimes 5431592Srgrimes/* 5441592Srgrimes** SendPacket -- send an RMP packet to a remote host. 5451592Srgrimes** 5461592Srgrimes** Parameters: 5471592Srgrimes** rconn - packet to be sent. 5481592Srgrimes** 5491592Srgrimes** Returns: 5501592Srgrimes** 1 on success, 0 on failure. 5511592Srgrimes** 5521592Srgrimes** Side Effects: 5531592Srgrimes** none. 5541592Srgrimes*/ 5551592Srgrimesint 55690377SimpSendPacket(RMPCONN *rconn) 5571592Srgrimes{ 5581592Srgrimes /* 5591592Srgrimes * Set Ethernet Destination address to Source (BPF and the enet 5601592Srgrimes * driver will take care of getting our source address set). 5611592Srgrimes */ 56227079Ssteve memmove((char *)&rconn->rmp.hp_hdr.daddr[0], 56327079Ssteve (char *)&rconn->rmp.hp_hdr.saddr[0], RMP_ADDRLEN); 56427074Ssteve rconn->rmp.hp_hdr.len = htons(rconn->rmplen - sizeof(struct hp_hdr)); 5651592Srgrimes 5661592Srgrimes /* 5671592Srgrimes * Reverse 802.2/HP Extended Source & Destination Access Pts. 5681592Srgrimes */ 56927074Ssteve rconn->rmp.hp_llc.dxsap = htons(HPEXT_SXSAP); 57027074Ssteve rconn->rmp.hp_llc.sxsap = htons(HPEXT_DXSAP); 5711592Srgrimes 5721592Srgrimes /* 5731592Srgrimes * Last time this connection was active. 5741592Srgrimes */ 575239991Sed (void)gettimeofday(&rconn->tstamp, NULL); 5761592Srgrimes 5771592Srgrimes if (DbgFp != NULL) /* display packet */ 5781592Srgrimes DispPkt(rconn,DIR_SENT); 5791592Srgrimes 5801592Srgrimes /* 5811592Srgrimes * Send RMP packet to remote host. 5821592Srgrimes */ 5831592Srgrimes return(BpfWrite(rconn)); 5841592Srgrimes} 585