10559b331SSteve Price /* 20559b331SSteve Price * Copyright (c) 1988, 1992 The University of Utah and the Center 30559b331SSteve Price * for Software Science (CSS). 40559b331SSteve Price * Copyright (c) 1992, 1993 50559b331SSteve Price * The Regents of the University of California. All rights reserved. 60559b331SSteve Price * 70559b331SSteve Price * This code is derived from software contributed to Berkeley by 80559b331SSteve Price * the Center for Software Science of the University of Utah Computer 90559b331SSteve Price * Science Department. CSS requests users of this software to return 100559b331SSteve Price * to css-dist@cs.utah.edu any improvements that they make and grant 110559b331SSteve Price * CSS redistribution rights. 120559b331SSteve Price * 130559b331SSteve Price * Redistribution and use in source and binary forms, with or without 140559b331SSteve Price * modification, are permitted provided that the following conditions 150559b331SSteve Price * are met: 160559b331SSteve Price * 1. Redistributions of source code must retain the above copyright 170559b331SSteve Price * notice, this list of conditions and the following disclaimer. 180559b331SSteve Price * 2. Redistributions in binary form must reproduce the above copyright 190559b331SSteve Price * notice, this list of conditions and the following disclaimer in the 200559b331SSteve Price * documentation and/or other materials provided with the distribution. 210559b331SSteve Price * 3. All advertising materials mentioning features or use of this software 220559b331SSteve Price * must display the following acknowledgement: 230559b331SSteve Price * This product includes software developed by the University of 240559b331SSteve Price * California, Berkeley and its contributors. 250559b331SSteve Price * 4. Neither the name of the University nor the names of its contributors 260559b331SSteve Price * may be used to endorse or promote products derived from this software 270559b331SSteve Price * without specific prior written permission. 280559b331SSteve Price * 290559b331SSteve Price * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 300559b331SSteve Price * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 310559b331SSteve Price * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 320559b331SSteve Price * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 330559b331SSteve Price * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 340559b331SSteve Price * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 350559b331SSteve Price * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 360559b331SSteve Price * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 370559b331SSteve Price * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 380559b331SSteve Price * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 390559b331SSteve Price * SUCH DAMAGE. 400559b331SSteve Price * 410559b331SSteve Price * from: @(#)rmpproto.c 8.1 (Berkeley) 6/4/93 420559b331SSteve Price * 430559b331SSteve Price * From: Utah Hdr: rmpproto.c 3.1 92/07/06 440559b331SSteve Price * Author: Jeff Forys, University of Utah CSS 450559b331SSteve Price */ 460559b331SSteve Price 470559b331SSteve Price #ifndef lint 48eb0b8290SPhilippe Charnier #if 0 495c8709fdSSteve Price static const char sccsid[] = "@(#)rmpproto.c 8.1 (Berkeley) 6/4/93"; 50eb0b8290SPhilippe Charnier #endif 51eb0b8290SPhilippe Charnier static const char rcsid[] = 527f3dea24SPeter Wemm "$FreeBSD$"; 530559b331SSteve Price #endif /* not lint */ 540559b331SSteve Price 550559b331SSteve Price #include <sys/param.h> 560559b331SSteve Price #include <sys/time.h> 570559b331SSteve Price 580559b331SSteve Price #include <errno.h> 590559b331SSteve Price #include <fcntl.h> 600559b331SSteve Price #include <stdio.h> 610559b331SSteve Price #include <string.h> 620559b331SSteve Price #include <syslog.h> 630559b331SSteve Price #include <unistd.h> 640559b331SSteve Price #include "defs.h" 650559b331SSteve Price 660559b331SSteve Price /* 670559b331SSteve Price ** ProcessPacket -- determine packet type and do what's required. 680559b331SSteve Price ** 690559b331SSteve Price ** An RMP BOOT packet has been received. Look at the type field 700559b331SSteve Price ** and process Boot Requests, Read Requests, and Boot Complete 710559b331SSteve Price ** packets. Any other type will be dropped with a warning msg. 720559b331SSteve Price ** 730559b331SSteve Price ** Parameters: 740559b331SSteve Price ** rconn - the new connection 750559b331SSteve Price ** client - list of files available to this host 760559b331SSteve Price ** 770559b331SSteve Price ** Returns: 780559b331SSteve Price ** Nothing. 790559b331SSteve Price ** 800559b331SSteve Price ** Side Effects: 810559b331SSteve Price ** - If this is a valid boot request, it will be added to 820559b331SSteve Price ** the linked list of outstanding requests (RmpConns). 830559b331SSteve Price ** - If this is a valid boot complete, its associated 840559b331SSteve Price ** entry in RmpConns will be deleted. 850559b331SSteve Price ** - Also, unless we run out of memory, a reply will be 860559b331SSteve Price ** sent to the host that sent the packet. 870559b331SSteve Price */ 880559b331SSteve Price void 890559b331SSteve Price ProcessPacket(rconn, client) 900559b331SSteve Price RMPCONN *rconn; 910559b331SSteve Price CLIENT *client; 920559b331SSteve Price { 930559b331SSteve Price struct rmp_packet *rmp; 940559b331SSteve Price RMPCONN *rconnout; 950559b331SSteve Price 960559b331SSteve Price rmp = &rconn->rmp; /* cache pointer to RMP packet */ 970559b331SSteve Price 980559b331SSteve Price switch(rmp->r_type) { /* do what we came here to do */ 990559b331SSteve Price case RMP_BOOT_REQ: /* boot request */ 1000559b331SSteve Price if ((rconnout = NewConn(rconn)) == NULL) 1010559b331SSteve Price return; 1020559b331SSteve Price 1030559b331SSteve Price /* 1040559b331SSteve Price * If the Session ID is 0xffff, this is a "probe" 1050559b331SSteve Price * packet and we do not want to add the connection 1060559b331SSteve Price * to the linked list of active connections. There 1070559b331SSteve Price * are two types of probe packets, if the Sequence 1080559b331SSteve Price * Number is 0 they want to know our host name, o/w 1090559b331SSteve Price * they want the name of the file associated with 1100559b331SSteve Price * the number spec'd by the Sequence Number. 1110559b331SSteve Price * 1120559b331SSteve Price * If this is an actual boot request, open the file 1130559b331SSteve Price * and send a reply. If SendBootRepl() does not 1140559b331SSteve Price * return 0, add the connection to the linked list 1150559b331SSteve Price * of active connections, otherwise delete it since 1160559b331SSteve Price * an error was encountered. 1170559b331SSteve Price */ 1180559b331SSteve Price if (ntohs(rmp->r_brq.rmp_session) == RMP_PROBESID) { 1190559b331SSteve Price if (WORDZE(rmp->r_brq.rmp_seqno)) 1200559b331SSteve Price (void) SendServerID(rconnout); 1210559b331SSteve Price else 1220559b331SSteve Price (void) SendFileNo(rmp, rconnout, 1230559b331SSteve Price client? client->files: 1240559b331SSteve Price BootFiles); 1250559b331SSteve Price FreeConn(rconnout); 1260559b331SSteve Price } else { 1270559b331SSteve Price if (SendBootRepl(rmp, rconnout, 1280559b331SSteve Price client? client->files: BootFiles)) 1290559b331SSteve Price AddConn(rconnout); 1300559b331SSteve Price else 1310559b331SSteve Price FreeConn(rconnout); 1320559b331SSteve Price } 1330559b331SSteve Price break; 1340559b331SSteve Price 1350559b331SSteve Price case RMP_BOOT_REPL: /* boot reply (not valid) */ 1360559b331SSteve Price syslog(LOG_WARNING, "%s: sent a boot reply", 1370559b331SSteve Price EnetStr(rconn)); 1380559b331SSteve Price break; 1390559b331SSteve Price 1400559b331SSteve Price case RMP_READ_REQ: /* read request */ 1410559b331SSteve Price /* 1420559b331SSteve Price * Send a portion of the boot file. 1430559b331SSteve Price */ 1440559b331SSteve Price (void) SendReadRepl(rconn); 1450559b331SSteve Price break; 1460559b331SSteve Price 1470559b331SSteve Price case RMP_READ_REPL: /* read reply (not valid) */ 1480559b331SSteve Price syslog(LOG_WARNING, "%s: sent a read reply", 1490559b331SSteve Price EnetStr(rconn)); 1500559b331SSteve Price break; 1510559b331SSteve Price 1520559b331SSteve Price case RMP_BOOT_DONE: /* boot complete */ 1530559b331SSteve Price /* 1540559b331SSteve Price * Remove the entry from the linked list of active 1550559b331SSteve Price * connections. 1560559b331SSteve Price */ 1570559b331SSteve Price (void) BootDone(rconn); 1580559b331SSteve Price break; 1590559b331SSteve Price 1600559b331SSteve Price default: /* unknown RMP packet type */ 1610559b331SSteve Price syslog(LOG_WARNING, "%s: unknown packet type (%u)", 1620559b331SSteve Price EnetStr(rconn), rmp->r_type); 1630559b331SSteve Price } 1640559b331SSteve Price } 1650559b331SSteve Price 1660559b331SSteve Price /* 1670559b331SSteve Price ** SendServerID -- send our host name to who ever requested it. 1680559b331SSteve Price ** 1690559b331SSteve Price ** Parameters: 1700559b331SSteve Price ** rconn - the reply packet to be formatted. 1710559b331SSteve Price ** 1720559b331SSteve Price ** Returns: 1730559b331SSteve Price ** 1 on success, 0 on failure. 1740559b331SSteve Price ** 1750559b331SSteve Price ** Side Effects: 1760559b331SSteve Price ** none. 1770559b331SSteve Price */ 1780559b331SSteve Price int 1790559b331SSteve Price SendServerID(rconn) 1800559b331SSteve Price RMPCONN *rconn; 1810559b331SSteve Price { 18211fe7d5eSSteve Price struct rmp_packet *rpl; 18311fe7d5eSSteve Price char *src, *dst; 18411fe7d5eSSteve Price u_int8_t *size; 1850559b331SSteve Price 1860559b331SSteve Price rpl = &rconn->rmp; /* cache ptr to RMP packet */ 1870559b331SSteve Price 1880559b331SSteve Price /* 1890559b331SSteve Price * Set up assorted fields in reply packet. 1900559b331SSteve Price */ 1910559b331SSteve Price rpl->r_brpl.rmp_type = RMP_BOOT_REPL; 1920559b331SSteve Price rpl->r_brpl.rmp_retcode = RMP_E_OKAY; 1930559b331SSteve Price ZEROWORD(rpl->r_brpl.rmp_seqno); 1940559b331SSteve Price rpl->r_brpl.rmp_session = 0; 1950559b331SSteve Price rpl->r_brpl.rmp_version = htons(RMP_VERSION); 1960559b331SSteve Price 1970559b331SSteve Price size = &rpl->r_brpl.rmp_flnmsize; /* ptr to length of host name */ 1980559b331SSteve Price 1990559b331SSteve Price /* 2000559b331SSteve Price * Copy our host name into the reply packet incrementing the 2010559b331SSteve Price * length as we go. Stop at RMP_HOSTLEN or the first dot. 2020559b331SSteve Price */ 2030559b331SSteve Price src = MyHost; 2040559b331SSteve Price dst = (char *) &rpl->r_brpl.rmp_flnm; 2050559b331SSteve Price for (*size = 0; *size < RMP_HOSTLEN; (*size)++) { 2060559b331SSteve Price if (*src == '.' || *src == '\0') 2070559b331SSteve Price break; 2080559b331SSteve Price *dst++ = *src++; 2090559b331SSteve Price } 2100559b331SSteve Price 2110559b331SSteve Price rconn->rmplen = RMPBOOTSIZE(*size); /* set packet length */ 2120559b331SSteve Price 2130559b331SSteve Price return(SendPacket(rconn)); /* send packet */ 2140559b331SSteve Price } 2150559b331SSteve Price 2160559b331SSteve Price /* 2170559b331SSteve Price ** SendFileNo -- send the name of a bootable file to the requester. 2180559b331SSteve Price ** 2190559b331SSteve Price ** Parameters: 2200559b331SSteve Price ** req - RMP BOOT packet containing the request. 2210559b331SSteve Price ** rconn - the reply packet to be formatted. 2220559b331SSteve Price ** filelist - list of files available to the requester. 2230559b331SSteve Price ** 2240559b331SSteve Price ** Returns: 2250559b331SSteve Price ** 1 on success, 0 on failure. 2260559b331SSteve Price ** 2270559b331SSteve Price ** Side Effects: 2280559b331SSteve Price ** none. 2290559b331SSteve Price */ 2300559b331SSteve Price int 2310559b331SSteve Price SendFileNo(req, rconn, filelist) 2320559b331SSteve Price struct rmp_packet *req; 2330559b331SSteve Price RMPCONN *rconn; 2340559b331SSteve Price char *filelist[]; 2350559b331SSteve Price { 23611fe7d5eSSteve Price struct rmp_packet *rpl; 23711fe7d5eSSteve Price char *src, *dst; 23811fe7d5eSSteve Price u_int8_t *size; 23911fe7d5eSSteve Price int i; 2400559b331SSteve Price 2410559b331SSteve Price GETWORD(req->r_brpl.rmp_seqno, i); /* SeqNo is really FileNo */ 2420559b331SSteve Price rpl = &rconn->rmp; /* cache ptr to RMP packet */ 2430559b331SSteve Price 2440559b331SSteve Price /* 2450559b331SSteve Price * Set up assorted fields in reply packet. 2460559b331SSteve Price */ 2470559b331SSteve Price rpl->r_brpl.rmp_type = RMP_BOOT_REPL; 2480559b331SSteve Price PUTWORD(i, rpl->r_brpl.rmp_seqno); 2490559b331SSteve Price i--; 2500559b331SSteve Price rpl->r_brpl.rmp_session = 0; 2510559b331SSteve Price rpl->r_brpl.rmp_version = htons(RMP_VERSION); 2520559b331SSteve Price 2530559b331SSteve Price size = &rpl->r_brpl.rmp_flnmsize; /* ptr to length of filename */ 2540559b331SSteve Price *size = 0; /* init length to zero */ 2550559b331SSteve Price 2560559b331SSteve Price /* 2570559b331SSteve Price * Copy the file name into the reply packet incrementing the 2580559b331SSteve Price * length as we go. Stop at end of string or when RMPBOOTDATA 2590559b331SSteve Price * characters have been copied. Also, set return code to 2600559b331SSteve Price * indicate success or "no more files". 2610559b331SSteve Price */ 2620559b331SSteve Price if (i < C_MAXFILE && filelist[i] != NULL) { 2630559b331SSteve Price src = filelist[i]; 2640559b331SSteve Price dst = (char *)&rpl->r_brpl.rmp_flnm; 2650559b331SSteve Price for (; *src && *size < RMPBOOTDATA; (*size)++) { 2660559b331SSteve Price if (*src == '\0') 2670559b331SSteve Price break; 2680559b331SSteve Price *dst++ = *src++; 2690559b331SSteve Price } 2700559b331SSteve Price rpl->r_brpl.rmp_retcode = RMP_E_OKAY; 2710559b331SSteve Price } else 2720559b331SSteve Price rpl->r_brpl.rmp_retcode = RMP_E_NODFLT; 2730559b331SSteve Price 2740559b331SSteve Price rconn->rmplen = RMPBOOTSIZE(*size); /* set packet length */ 2750559b331SSteve Price 2760559b331SSteve Price return(SendPacket(rconn)); /* send packet */ 2770559b331SSteve Price } 2780559b331SSteve Price 2790559b331SSteve Price /* 2800559b331SSteve Price ** SendBootRepl -- open boot file and respond to boot request. 2810559b331SSteve Price ** 2820559b331SSteve Price ** Parameters: 2830559b331SSteve Price ** req - RMP BOOT packet containing the request. 2840559b331SSteve Price ** rconn - the reply packet to be formatted. 2850559b331SSteve Price ** filelist - list of files available to the requester. 2860559b331SSteve Price ** 2870559b331SSteve Price ** Returns: 2880559b331SSteve Price ** 1 on success, 0 on failure. 2890559b331SSteve Price ** 2900559b331SSteve Price ** Side Effects: 2910559b331SSteve Price ** none. 2920559b331SSteve Price */ 2930559b331SSteve Price int 2940559b331SSteve Price SendBootRepl(req, rconn, filelist) 2950559b331SSteve Price struct rmp_packet *req; 2960559b331SSteve Price RMPCONN *rconn; 2970559b331SSteve Price char *filelist[]; 2980559b331SSteve Price { 2990559b331SSteve Price int retval; 3000559b331SSteve Price char *filename, filepath[RMPBOOTDATA+1]; 3010559b331SSteve Price RMPCONN *oldconn; 30211fe7d5eSSteve Price struct rmp_packet *rpl; 30311fe7d5eSSteve Price char *src, *dst1, *dst2; 30411fe7d5eSSteve Price u_int8_t i; 3050559b331SSteve Price 3060559b331SSteve Price /* 3070559b331SSteve Price * If another connection already exists, delete it since we 3080559b331SSteve Price * are obviously starting again. 3090559b331SSteve Price */ 3100559b331SSteve Price if ((oldconn = FindConn(rconn)) != NULL) { 3110559b331SSteve Price syslog(LOG_WARNING, "%s: dropping existing connection", 3120559b331SSteve Price EnetStr(oldconn)); 3130559b331SSteve Price RemoveConn(oldconn); 3140559b331SSteve Price } 3150559b331SSteve Price 3160559b331SSteve Price rpl = &rconn->rmp; /* cache ptr to RMP packet */ 3170559b331SSteve Price 3180559b331SSteve Price /* 3190559b331SSteve Price * Set up assorted fields in reply packet. 3200559b331SSteve Price */ 3210559b331SSteve Price rpl->r_brpl.rmp_type = RMP_BOOT_REPL; 3220559b331SSteve Price COPYWORD(req->r_brq.rmp_seqno, rpl->r_brpl.rmp_seqno); 3230559b331SSteve Price rpl->r_brpl.rmp_session = htons(GenSessID()); 3240559b331SSteve Price rpl->r_brpl.rmp_version = htons(RMP_VERSION); 3250559b331SSteve Price rpl->r_brpl.rmp_flnmsize = req->r_brq.rmp_flnmsize; 3260559b331SSteve Price 3270559b331SSteve Price /* 3280559b331SSteve Price * Copy file name to `filepath' string, and into reply packet. 3290559b331SSteve Price */ 3300559b331SSteve Price src = &req->r_brq.rmp_flnm; 3310559b331SSteve Price dst1 = filepath; 3320559b331SSteve Price dst2 = &rpl->r_brpl.rmp_flnm; 3330559b331SSteve Price for (i = 0; i < req->r_brq.rmp_flnmsize; i++) 3340559b331SSteve Price *dst1++ = *dst2++ = *src++; 3350559b331SSteve Price *dst1 = '\0'; 3360559b331SSteve Price 3370559b331SSteve Price /* 3380559b331SSteve Price * If we are booting HP-UX machines, their secondary loader will 3390559b331SSteve Price * ask for files like "/hp-ux". As a security measure, we do not 3400559b331SSteve Price * allow boot files to lay outside the boot directory (unless they 3410559b331SSteve Price * are purposely link'd out. So, make `filename' become the path- 3420559b331SSteve Price * stripped file name and spoof the client into thinking that it 3430559b331SSteve Price * really got what it wanted. 3440559b331SSteve Price */ 34511fe7d5eSSteve Price filename = (filename = strrchr(filepath,'/'))? ++filename: filepath; 3460559b331SSteve Price 3470559b331SSteve Price /* 3480559b331SSteve Price * Check that this is a valid boot file name. 3490559b331SSteve Price */ 3500559b331SSteve Price for (i = 0; i < C_MAXFILE && filelist[i] != NULL; i++) 3510559b331SSteve Price if (STREQN(filename, filelist[i])) 3520559b331SSteve Price goto match; 3530559b331SSteve Price 3540559b331SSteve Price /* 3550559b331SSteve Price * Invalid boot file name, set error and send reply packet. 3560559b331SSteve Price */ 3570559b331SSteve Price rpl->r_brpl.rmp_retcode = RMP_E_NOFILE; 3580559b331SSteve Price retval = 0; 3590559b331SSteve Price goto sendpkt; 3600559b331SSteve Price 3610559b331SSteve Price match: 3620559b331SSteve Price /* 3630559b331SSteve Price * This is a valid boot file. Open the file and save the file 3640559b331SSteve Price * descriptor associated with this connection and set success 3650559b331SSteve Price * indication. If the file couldnt be opened, set error: 3660559b331SSteve Price * "no such file or dir" - RMP_E_NOFILE 3670559b331SSteve Price * "file table overflow" - RMP_E_BUSY 3680559b331SSteve Price * "too many open files" - RMP_E_BUSY 3690559b331SSteve Price * anything else - RMP_E_OPENFILE 3700559b331SSteve Price */ 3710559b331SSteve Price if ((rconn->bootfd = open(filename, O_RDONLY, 0600)) < 0) { 3720559b331SSteve Price rpl->r_brpl.rmp_retcode = (errno == ENOENT)? RMP_E_NOFILE: 3730559b331SSteve Price (errno == EMFILE || errno == ENFILE)? RMP_E_BUSY: 3740559b331SSteve Price RMP_E_OPENFILE; 3750559b331SSteve Price retval = 0; 3760559b331SSteve Price } else { 3770559b331SSteve Price rpl->r_brpl.rmp_retcode = RMP_E_OKAY; 3780559b331SSteve Price retval = 1; 3790559b331SSteve Price } 3800559b331SSteve Price 3810559b331SSteve Price sendpkt: 3820559b331SSteve Price syslog(LOG_INFO, "%s: request to boot %s (%s)", 3830559b331SSteve Price EnetStr(rconn), filename, retval? "granted": "denied"); 3840559b331SSteve Price 3850559b331SSteve Price rconn->rmplen = RMPBOOTSIZE(rpl->r_brpl.rmp_flnmsize); 3860559b331SSteve Price 3870559b331SSteve Price return (retval & SendPacket(rconn)); 3880559b331SSteve Price } 3890559b331SSteve Price 3900559b331SSteve Price /* 3910559b331SSteve Price ** SendReadRepl -- send a portion of the boot file to the requester. 3920559b331SSteve Price ** 3930559b331SSteve Price ** Parameters: 3940559b331SSteve Price ** rconn - the reply packet to be formatted. 3950559b331SSteve Price ** 3960559b331SSteve Price ** Returns: 3970559b331SSteve Price ** 1 on success, 0 on failure. 3980559b331SSteve Price ** 3990559b331SSteve Price ** Side Effects: 4000559b331SSteve Price ** none. 4010559b331SSteve Price */ 4020559b331SSteve Price int 4030559b331SSteve Price SendReadRepl(rconn) 4040559b331SSteve Price RMPCONN *rconn; 4050559b331SSteve Price { 4060559b331SSteve Price int retval = 0; 4070559b331SSteve Price RMPCONN *oldconn; 40811fe7d5eSSteve Price struct rmp_packet *rpl, *req; 40911fe7d5eSSteve Price int size = 0; 4100559b331SSteve Price int madeconn = 0; 4110559b331SSteve Price 4120559b331SSteve Price /* 4130559b331SSteve Price * Find the old connection. If one doesnt exist, create one only 4140559b331SSteve Price * to return the error code. 4150559b331SSteve Price */ 4160559b331SSteve Price if ((oldconn = FindConn(rconn)) == NULL) { 4170559b331SSteve Price if ((oldconn = NewConn(rconn)) == NULL) 4180559b331SSteve Price return(0); 4190559b331SSteve Price syslog(LOG_ERR, "SendReadRepl: no active connection (%s)", 4200559b331SSteve Price EnetStr(rconn)); 4210559b331SSteve Price madeconn++; 4220559b331SSteve Price } 4230559b331SSteve Price 4240559b331SSteve Price req = &rconn->rmp; /* cache ptr to request packet */ 4250559b331SSteve Price rpl = &oldconn->rmp; /* cache ptr to reply packet */ 4260559b331SSteve Price 4270559b331SSteve Price if (madeconn) { /* no active connection above; abort */ 4280559b331SSteve Price rpl->r_rrpl.rmp_retcode = RMP_E_ABORT; 4290559b331SSteve Price retval = 1; 4300559b331SSteve Price goto sendpkt; 4310559b331SSteve Price } 4320559b331SSteve Price 4330559b331SSteve Price /* 4340559b331SSteve Price * Make sure Session ID's match. 4350559b331SSteve Price */ 4360559b331SSteve Price if (ntohs(req->r_rrq.rmp_session) != 4370559b331SSteve Price ((rpl->r_type == RMP_BOOT_REPL)? ntohs(rpl->r_brpl.rmp_session): 4380559b331SSteve Price ntohs(rpl->r_rrpl.rmp_session))) { 4390559b331SSteve Price syslog(LOG_ERR, "SendReadRepl: bad session id (%s)", 4400559b331SSteve Price EnetStr(rconn)); 4410559b331SSteve Price rpl->r_rrpl.rmp_retcode = RMP_E_BADSID; 4420559b331SSteve Price retval = 1; 4430559b331SSteve Price goto sendpkt; 4440559b331SSteve Price } 4450559b331SSteve Price 4460559b331SSteve Price /* 4470559b331SSteve Price * If the requester asks for more data than we can fit, 4480559b331SSteve Price * silently clamp the request size down to RMPREADDATA. 4490559b331SSteve Price * 4500559b331SSteve Price * N.B. I do not know if this is "legal", however it seems 4510559b331SSteve Price * to work. This is necessary for bpfwrite() on machines 4520559b331SSteve Price * with MCLBYTES less than 1514. 4530559b331SSteve Price */ 4540559b331SSteve Price if (ntohs(req->r_rrq.rmp_size) > RMPREADDATA) 4550559b331SSteve Price req->r_rrq.rmp_size = htons(RMPREADDATA); 4560559b331SSteve Price 4570559b331SSteve Price /* 4580559b331SSteve Price * Position read head on file according to info in request packet. 4590559b331SSteve Price */ 4600559b331SSteve Price GETWORD(req->r_rrq.rmp_offset, size); 461e10471bbSKris Kennaway if (lseek(oldconn->bootfd, (off_t)size, SEEK_SET) < 0) { 4620559b331SSteve Price syslog(LOG_ERR, "SendReadRepl: lseek: %m (%s)", 4630559b331SSteve Price EnetStr(rconn)); 4640559b331SSteve Price rpl->r_rrpl.rmp_retcode = RMP_E_ABORT; 4650559b331SSteve Price retval = 1; 4660559b331SSteve Price goto sendpkt; 4670559b331SSteve Price } 4680559b331SSteve Price 4690559b331SSteve Price /* 4700559b331SSteve Price * Read data directly into reply packet. 4710559b331SSteve Price */ 4720559b331SSteve Price if ((size = read(oldconn->bootfd, &rpl->r_rrpl.rmp_data, 4730559b331SSteve Price (int) ntohs(req->r_rrq.rmp_size))) <= 0) { 4740559b331SSteve Price if (size < 0) { 4750559b331SSteve Price syslog(LOG_ERR, "SendReadRepl: read: %m (%s)", 4760559b331SSteve Price EnetStr(rconn)); 4770559b331SSteve Price rpl->r_rrpl.rmp_retcode = RMP_E_ABORT; 4780559b331SSteve Price } else { 4790559b331SSteve Price rpl->r_rrpl.rmp_retcode = RMP_E_EOF; 4800559b331SSteve Price } 4810559b331SSteve Price retval = 1; 4820559b331SSteve Price goto sendpkt; 4830559b331SSteve Price } 4840559b331SSteve Price 4850559b331SSteve Price /* 4860559b331SSteve Price * Set success indication. 4870559b331SSteve Price */ 4880559b331SSteve Price rpl->r_rrpl.rmp_retcode = RMP_E_OKAY; 4890559b331SSteve Price 4900559b331SSteve Price sendpkt: 4910559b331SSteve Price /* 4920559b331SSteve Price * Set up assorted fields in reply packet. 4930559b331SSteve Price */ 4940559b331SSteve Price rpl->r_rrpl.rmp_type = RMP_READ_REPL; 4950559b331SSteve Price COPYWORD(req->r_rrq.rmp_offset, rpl->r_rrpl.rmp_offset); 4960559b331SSteve Price rpl->r_rrpl.rmp_session = req->r_rrq.rmp_session; 4970559b331SSteve Price 4980559b331SSteve Price oldconn->rmplen = RMPREADSIZE(size); /* set size of packet */ 4990559b331SSteve Price 5000559b331SSteve Price retval &= SendPacket(oldconn); /* send packet */ 5010559b331SSteve Price 5020559b331SSteve Price if (madeconn) /* clean up after ourself */ 5030559b331SSteve Price FreeConn(oldconn); 5040559b331SSteve Price 5050559b331SSteve Price return (retval); 5060559b331SSteve Price } 5070559b331SSteve Price 5080559b331SSteve Price /* 5090559b331SSteve Price ** BootDone -- free up memory allocated for a connection. 5100559b331SSteve Price ** 5110559b331SSteve Price ** Parameters: 5120559b331SSteve Price ** rconn - incoming boot complete packet. 5130559b331SSteve Price ** 5140559b331SSteve Price ** Returns: 5150559b331SSteve Price ** 1 on success, 0 on failure. 5160559b331SSteve Price ** 5170559b331SSteve Price ** Side Effects: 5180559b331SSteve Price ** none. 5190559b331SSteve Price */ 5200559b331SSteve Price int 5210559b331SSteve Price BootDone(rconn) 5220559b331SSteve Price RMPCONN *rconn; 5230559b331SSteve Price { 5240559b331SSteve Price RMPCONN *oldconn; 5250559b331SSteve Price struct rmp_packet *rpl; 5260559b331SSteve Price 5270559b331SSteve Price /* 5280559b331SSteve Price * If we cant find the connection, ignore the request. 5290559b331SSteve Price */ 5300559b331SSteve Price if ((oldconn = FindConn(rconn)) == NULL) { 5310559b331SSteve Price syslog(LOG_ERR, "BootDone: no existing connection (%s)", 5320559b331SSteve Price EnetStr(rconn)); 5330559b331SSteve Price return(0); 5340559b331SSteve Price } 5350559b331SSteve Price 5360559b331SSteve Price rpl = &oldconn->rmp; /* cache ptr to RMP packet */ 5370559b331SSteve Price 5380559b331SSteve Price /* 5390559b331SSteve Price * Make sure Session ID's match. 5400559b331SSteve Price */ 5410559b331SSteve Price if (ntohs(rconn->rmp.r_rrq.rmp_session) != 5420559b331SSteve Price ((rpl->r_type == RMP_BOOT_REPL)? ntohs(rpl->r_brpl.rmp_session): 5430559b331SSteve Price ntohs(rpl->r_rrpl.rmp_session))) { 5440559b331SSteve Price syslog(LOG_ERR, "BootDone: bad session id (%s)", 5450559b331SSteve Price EnetStr(rconn)); 5460559b331SSteve Price return(0); 5470559b331SSteve Price } 5480559b331SSteve Price 5490559b331SSteve Price RemoveConn(oldconn); /* remove connection */ 5500559b331SSteve Price 5510559b331SSteve Price syslog(LOG_INFO, "%s: boot complete", EnetStr(rconn)); 5520559b331SSteve Price 5530559b331SSteve Price return(1); 5540559b331SSteve Price } 5550559b331SSteve Price 5560559b331SSteve Price /* 5570559b331SSteve Price ** SendPacket -- send an RMP packet to a remote host. 5580559b331SSteve Price ** 5590559b331SSteve Price ** Parameters: 5600559b331SSteve Price ** rconn - packet to be sent. 5610559b331SSteve Price ** 5620559b331SSteve Price ** Returns: 5630559b331SSteve Price ** 1 on success, 0 on failure. 5640559b331SSteve Price ** 5650559b331SSteve Price ** Side Effects: 5660559b331SSteve Price ** none. 5670559b331SSteve Price */ 5680559b331SSteve Price int 5690559b331SSteve Price SendPacket(rconn) 57011fe7d5eSSteve Price RMPCONN *rconn; 5710559b331SSteve Price { 5720559b331SSteve Price /* 5730559b331SSteve Price * Set Ethernet Destination address to Source (BPF and the enet 5740559b331SSteve Price * driver will take care of getting our source address set). 5750559b331SSteve Price */ 57611fe7d5eSSteve Price memmove((char *)&rconn->rmp.hp_hdr.daddr[0], 57711fe7d5eSSteve Price (char *)&rconn->rmp.hp_hdr.saddr[0], RMP_ADDRLEN); 5780559b331SSteve Price rconn->rmp.hp_hdr.len = htons(rconn->rmplen - sizeof(struct hp_hdr)); 5790559b331SSteve Price 5800559b331SSteve Price /* 5810559b331SSteve Price * Reverse 802.2/HP Extended Source & Destination Access Pts. 5820559b331SSteve Price */ 5830559b331SSteve Price rconn->rmp.hp_llc.dxsap = htons(HPEXT_SXSAP); 5840559b331SSteve Price rconn->rmp.hp_llc.sxsap = htons(HPEXT_DXSAP); 5850559b331SSteve Price 5860559b331SSteve Price /* 5870559b331SSteve Price * Last time this connection was active. 5880559b331SSteve Price */ 5890559b331SSteve Price (void) gettimeofday(&rconn->tstamp, (struct timezone *)0); 5900559b331SSteve Price 5910559b331SSteve Price if (DbgFp != NULL) /* display packet */ 5920559b331SSteve Price DispPkt(rconn,DIR_SENT); 5930559b331SSteve Price 5940559b331SSteve Price /* 5950559b331SSteve Price * Send RMP packet to remote host. 5960559b331SSteve Price */ 5970559b331SSteve Price return(BpfWrite(rconn)); 5980559b331SSteve Price } 599