FreeBSD/libexec/tftpd/tftp-transfer.c
/*
 * Send a file via the TFTP data session.
 */
Send a file via the TFTP data session.
Send a file via the TFTP data session .
void
tftp_send(int peer, uint16_t *block, struct tftp_stats *ts)
{
	struct tftphdr *rp;
	int size, n_data, n_ack, try;
	uint16_t oldblock;
	char sendbuffer[MAXPKTSIZE];
	char recvbuffer[MAXPKTSIZE];
	rp = (struct tftphdr *)recvbuffer;
	*block = 1;
	ts->amount = 0;
	do {
		if (debug&DEBUG_SIMPLE)
			tftp_log(LOG_DEBUG, "Sending block %d", *block);
		size = read_file(sendbuffer, segsize);
		if (size < 0) {
			tftp_log(LOG_ERR, "read_file returned %d", size);
			send_error(peer, errno + 100);
			goto abort;
		}
		for (try = 0; ; try++) {
			n_data = send_data(peer, *block, sendbuffer, size);
			if (n_data > 0) {
				if (try == maxtimeouts) {
					tftp_log(LOG_ERR,
					    "Cannot send DATA packet #%d, "
					    "giving up", *block);
					return;
				}
				tftp_log(LOG_ERR,
				    "Cannot send DATA packet #%d, trying again",
				    *block);
				continue;
			}
			n_ack = receive_packet(peer, recvbuffer,
			    MAXPKTSIZE, NULL, timeoutpacket);
			if (n_ack < 0) {
				if (n_ack == RP_TIMEOUT) {
					if (try == maxtimeouts) {
						tftp_log(LOG_ERR,
						    "Timeout #%d send ACK %d "
						    "giving up", try, *block);
						return;
					}
					tftp_log(LOG_WARNING,
					    "Timeout #%d on ACK %d",
					    try, *block);
					continue;
				}
				if (debug&DEBUG_SIMPLE)
					tftp_log(LOG_ERR, "Aborting: %s",
					    rp_strerror(n_ack));
				goto abort;
			}
			if (rp->th_opcode == ACK) {
				ts->blocks++;
				if (rp->th_block == *block) {
					ts->amount += size;
					break;
				}
				(void) synchnet(peer);
				if (rp->th_block == (*block - 1)) {
					ts->retries++;
					continue;
				}
			}
		}
		oldblock = *block;
		(*block)++;
		if (oldblock > *block) {
			if (options[OPT_ROLLOVER].o_request == NULL) {
				*block = 0;
			} else {
				*block = atoi(options[OPT_ROLLOVER].o_request);
			}
			ts->rollovers++;
		}
		gettimeofday(&(ts->tstop), NULL);
	} while (size == segsize);
abort:
	return;
}
void tftp_send ( int peer , uint16_t * block , struct tftp_stats * ts ) { struct tftphdr * rp ; int size , n_data , n_ack , try ; uint16_t oldblock ; char sendbuffer [ MAXPKTSIZE ] ; char recvbuffer [ MAXPKTSIZE ] ; rp = ( struct tftphdr * ) recvbuffer ; * block = 1 ; ts -> amount = 0 ; do { if ( debug & DEBUG_SIMPLE ) tftp_log ( LOG_DEBUG , " " , * block ) ; size = read_file ( sendbuffer , segsize ) ; if ( size < 0 ) { tftp_log ( LOG_ERR , " " , size ) ; send_error ( peer , errno + 100 ) ; goto abort ; } for ( try = 0 ; ; try ++ ) { n_data = send_data ( peer , * block , sendbuffer , size ) ; if ( n_data > 0 ) { if ( try == maxtimeouts ) { tftp_log ( LOG_ERR , " " " " , * block ) ; return ; } tftp_log ( LOG_ERR , " " , * block ) ; continue ; } n_ack = receive_packet ( peer , recvbuffer , MAXPKTSIZE , NULL , timeoutpacket ) ; if ( n_ack < 0 ) { if ( n_ack == RP_TIMEOUT ) { if ( try == maxtimeouts ) { tftp_log ( LOG_ERR , " " " " , try , * block ) ; return ; } tftp_log ( LOG_WARNING , " " , try , * block ) ; continue ; } if ( debug & DEBUG_SIMPLE ) tftp_log ( LOG_ERR , " " , rp_strerror ( n_ack ) ) ; goto abort ; } if ( rp -> th_opcode == ACK ) { ts -> blocks ++ ; if ( rp -> th_block == * block ) { ts -> amount += size ; break ; } ( void ) synchnet ( peer ) ; if ( rp -> th_block == ( * block - 1 ) ) { ts -> retries ++ ; continue ; } } } oldblock = * block ; ( * block ) ++ ; if ( oldblock > * block ) { if ( options [ OPT_ROLLOVER ] . o_request == NULL ) { * block = 0 ; } else { * block = atoi ( options [ OPT_ROLLOVER ] . o_request ) ; } ts -> rollovers ++ ; } gettimeofday ( & ( ts -> tstop ) , NULL ) ; } while ( size == segsize ) ; abort : return ; }
Send a file via the TFTP data session.
Send a file via the TFTP data session .
/* Either read failure or ERROR packet */ /* Re-synchronize with the other side */ /*
				 * "rollover" option not specified in
				 * tftp client.  Default to rolling block
				 * counter to 0.
				 */