FreeBSD/libexec/tftpd/tftpd.c
/*
 * RRQ - send a file to the client
 */
send a file to the client
send a file to the client
void
tftp_rrq(int peer, char *recvbuffer, ssize_t size)
{
	char *cp;
	int has_options = 0, ecode;
	char *filename, *mode;
	char	fnbuf[PATH_MAX];
	cp = parse_header(peer, recvbuffer, size, &filename, &mode);
	size -= (cp - recvbuffer) + 1;
	strcpy(fnbuf, filename);
	reduce_path(fnbuf);
	filename = fnbuf;
	if (size > 0) {
		if (options_rfc_enabled)
			has_options = !parse_options(peer, cp, size);
		else
			tftp_log(LOG_INFO, "Options found but not enabled");
	}
	ecode = validate_access(peer, &filename, RRQ);
	if (ecode == 0) {
		if (has_options) {
			int n;
			char lrecvbuffer[MAXPKTSIZE];
			struct tftphdr *rp = (struct tftphdr *)lrecvbuffer;
			send_oack(peer);
			n = receive_packet(peer, lrecvbuffer, MAXPKTSIZE,
				NULL, timeoutpacket);
			if (n < 0) {
				if (debug&DEBUG_SIMPLE)
					tftp_log(LOG_DEBUG, "Aborting: %s",
					    rp_strerror(n));
				return;
			}
			if (rp->th_opcode != ACK) {
				if (debug&DEBUG_SIMPLE)
					tftp_log(LOG_DEBUG,
					    "Expected ACK, got %s on OACK",
					    packettype(rp->th_opcode));
				return;
			}
		}
	}
	if (logging)
		tftp_log(LOG_INFO, "%s: read request for %s: %s", peername,
			    filename, errtomsg(ecode));
	if (ecode) {
		if (suppress_naks && *filename != '/' && ecode == ENOTFOUND)
			exit(0);
		send_error(peer, ecode);
		exit(1);
	}
	tftp_xmitfile(peer, mode);
}
void tftp_rrq ( int peer , char * recvbuffer , ssize_t size ) { char * cp ; int has_options = 0 , ecode ; char * filename , * mode ; char fnbuf [ PATH_MAX ] ; cp = parse_header ( peer , recvbuffer , size , & filename , & mode ) ; size -= ( cp - recvbuffer ) + 1 ; strcpy ( fnbuf , filename ) ; reduce_path ( fnbuf ) ; filename = fnbuf ; if ( size > 0 ) { if ( options_rfc_enabled ) has_options = ! parse_options ( peer , cp , size ) ; else tftp_log ( LOG_INFO , " " ) ; } ecode = validate_access ( peer , & filename , RRQ ) ; if ( ecode == 0 ) { if ( has_options ) { int n ; char lrecvbuffer [ MAXPKTSIZE ] ; struct tftphdr * rp = ( struct tftphdr * ) lrecvbuffer ; send_oack ( peer ) ; n = receive_packet ( peer , lrecvbuffer , MAXPKTSIZE , NULL , timeoutpacket ) ; if ( n < 0 ) { if ( debug & DEBUG_SIMPLE ) tftp_log ( LOG_DEBUG , " " , rp_strerror ( n ) ) ; return ; } if ( rp -> th_opcode != ACK ) { if ( debug & DEBUG_SIMPLE ) tftp_log ( LOG_DEBUG , " " , packettype ( rp -> th_opcode ) ) ; return ; } } } if ( logging ) tftp_log ( LOG_INFO , " " , peername , filename , errtomsg ( ecode ) ) ; if ( ecode ) { if ( suppress_naks && * filename != ' ' && ecode == ENOTFOUND ) exit ( 0 ) ; send_error ( peer , ecode ) ; exit ( 1 ) ; } tftp_xmitfile ( peer , mode ) ; }
RRQ - send a file to the client
RRQ - send a file to the client
/*
		 * Avoid storms of naks to a RRQ broadcast for a relative
		 * bootfile pathname from a diskless Sun.
		 */