11590Srgrimes/* 21590Srgrimes * Copyright (c) 1983, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 3093428Sdwmalone#if 0 3193428Sdwmalone#ifndef lint 3293428Sdwmalonestatic char sccsid[] = "@(#)tftp.c 8.1 (Berkeley) 6/6/93"; 3393428Sdwmalone#endif /* not lint */ 3493428Sdwmalone#endif 3593428Sdwmalone 3687708Smarkm#include <sys/cdefs.h> 3787708Smarkm__FBSDID("$FreeBSD: stable/10/usr.bin/tftp/tftp.c 339060 2018-10-01 16:09:20Z asomers $"); 3887708Smarkm 391590Srgrimes/* Many bug fixes are from Jim Guyton <guyton@rand-unix> */ 401590Srgrimes 411590Srgrimes/* 421590Srgrimes * TFTP User Program -- Protocol Machines 431590Srgrimes */ 441590Srgrimes#include <sys/socket.h> 45207607Simp#include <sys/stat.h> 461590Srgrimes 471590Srgrimes#include <netinet/in.h> 481590Srgrimes 491590Srgrimes#include <arpa/tftp.h> 501590Srgrimes 51339060Sasomers#include <assert.h> 5228202Scharnier#include <err.h> 53207607Simp#include <netdb.h> 541590Srgrimes#include <stdio.h> 55207607Simp#include <stdlib.h> 5633645Sjb#include <string.h> 57207607Simp#include <syslog.h> 581590Srgrimes 59207607Simp#include "tftp.h" 60207607Simp#include "tftp-file.h" 61207607Simp#include "tftp-utils.h" 62207607Simp#include "tftp-io.h" 63207607Simp#include "tftp-transfer.h" 64207607Simp#include "tftp-options.h" 651590Srgrimes 661590Srgrimes/* 671590Srgrimes * Send the requested file. 681590Srgrimes */ 691590Srgrimesvoid 70207607Simpxmitfile(int peer, char *port, int fd, char *name, char *mode) 711590Srgrimes{ 72207607Simp struct tftphdr *rp; 73207607Simp int n, i; 74207607Simp uint16_t block; 7594443Sume struct sockaddr_storage serv; /* valid server port number */ 76207607Simp char recvbuffer[MAXPKTSIZE]; 77207607Simp struct tftp_stats tftp_stats; 781590Srgrimes 79207607Simp stats_init(&tftp_stats); 80207607Simp 8194443Sume memset(&serv, 0, sizeof(serv)); 82207607Simp rp = (struct tftphdr *)recvbuffer; 831590Srgrimes 84207607Simp if (port == NULL) { 85207607Simp struct servent *se; 86207607Simp se = getservbyname("tftp", "udp"); 87339060Sasomers assert(se != NULL); 88207607Simp ((struct sockaddr_in *)&peer_sock)->sin_port = se->s_port; 89207607Simp } else 90207607Simp ((struct sockaddr_in *)&peer_sock)->sin_port = 91207607Simp htons(atoi(port)); 92207607Simp 93207607Simp for (i = 0; i < 12; i++) { 94207607Simp struct sockaddr_storage from; 95207607Simp 96207607Simp /* Tell the other side what we want to do */ 97207607Simp if (debug&DEBUG_SIMPLE) 98207607Simp printf("Sending %s\n", name); 99207607Simp 100207607Simp n = send_wrq(peer, name, mode); 101207607Simp if (n > 0) { 102207607Simp printf("Cannot send WRQ packet\n"); 103207607Simp return; 1041590Srgrimes } 105207607Simp 106207607Simp /* 107207607Simp * The first packet we receive has the new destination port 108207607Simp * we have to send the next packets to. 109207607Simp */ 110207607Simp n = receive_packet(peer, recvbuffer, 111207607Simp MAXPKTSIZE, &from, timeoutpacket); 112207607Simp 113207607Simp /* We got some data! */ 114207607Simp if (n >= 0) { 115207607Simp ((struct sockaddr_in *)&peer_sock)->sin_port = 116207607Simp ((struct sockaddr_in *)&from)->sin_port; 117207607Simp break; 1181590Srgrimes } 1191590Srgrimes 120207607Simp /* This should be retried */ 121207607Simp if (n == RP_TIMEOUT) { 122207607Simp printf("Try %d, didn't receive answer from remote.\n", 123207607Simp i + 1); 124207607Simp continue; 1251590Srgrimes } 126207607Simp 127207607Simp /* Everything else is fatal */ 128207607Simp break; 129207607Simp } 130207607Simp if (i == 12) { 131207607Simp printf("Transfer timed out.\n"); 132207607Simp return; 133207607Simp } 134207607Simp if (rp->th_opcode == ERROR) { 135207607Simp printf("Got ERROR, aborted\n"); 136207607Simp return; 137207607Simp } 138207607Simp 139207607Simp /* 140207607Simp * If the first packet is an OACK instead of an ACK packet, 141207607Simp * handle it different. 142207607Simp */ 143207607Simp if (rp->th_opcode == OACK) { 144207607Simp if (!options_rfc_enabled) { 145207607Simp printf("Got OACK while options are not enabled!\n"); 146207607Simp send_error(peer, EBADOP); 147207607Simp return; 148207607Simp } 149207607Simp 150207607Simp parse_options(peer, rp->th_stuff, n + 2); 151207607Simp } 152207607Simp 153207607Simp if (read_init(fd, NULL, mode) < 0) { 154207607Simp warn("read_init()"); 155207607Simp return; 156207607Simp } 157207607Simp 158207607Simp block = 1; 159207607Simp tftp_send(peer, &block, &tftp_stats); 160207607Simp 161207607Simp read_close(); 162209551Sgavin if (tftp_stats.amount > 0) 163207607Simp printstats("Sent", verbose, &tftp_stats); 164207607Simp 165207607Simp txrx_error = 1; 1661590Srgrimes} 1671590Srgrimes 1681590Srgrimes/* 1691590Srgrimes * Receive a file. 1701590Srgrimes */ 1711590Srgrimesvoid 172207607Simprecvfile(int peer, char *port, int fd, char *name, char *mode) 1731590Srgrimes{ 174207607Simp struct tftphdr *rp; 175207607Simp uint16_t block; 176207607Simp char recvbuffer[MAXPKTSIZE]; 177207607Simp int n, i; 178207607Simp struct tftp_stats tftp_stats; 1791590Srgrimes 180207607Simp stats_init(&tftp_stats); 1811590Srgrimes 182207607Simp rp = (struct tftphdr *)recvbuffer; 1831590Srgrimes 184207607Simp if (port == NULL) { 185207607Simp struct servent *se; 186207607Simp se = getservbyname("tftp", "udp"); 187339060Sasomers assert(se != NULL); 188207607Simp ((struct sockaddr_in *)&peer_sock)->sin_port = se->s_port; 189207607Simp } else 190207607Simp ((struct sockaddr_in *)&peer_sock)->sin_port = 191207607Simp htons(atoi(port)); 1921590Srgrimes 193207607Simp for (i = 0; i < 12; i++) { 194207607Simp struct sockaddr_storage from; 1951590Srgrimes 196207607Simp /* Tell the other side what we want to do */ 197207607Simp if (debug&DEBUG_SIMPLE) 198207607Simp printf("Requesting %s\n", name); 1991590Srgrimes 200207607Simp n = send_rrq(peer, name, mode); 201207607Simp if (n > 0) { 202207607Simp printf("Cannot send RRQ packet\n"); 203207607Simp return; 204207607Simp } 2051590Srgrimes 206207607Simp /* 207207607Simp * The first packet we receive has the new destination port 208207607Simp * we have to send the next packets to. 209207607Simp */ 210207607Simp n = receive_packet(peer, recvbuffer, 211207607Simp MAXPKTSIZE, &from, timeoutpacket); 2121590Srgrimes 213207607Simp /* We got something useful! */ 214207607Simp if (n >= 0) { 215207607Simp ((struct sockaddr_in *)&peer_sock)->sin_port = 216207607Simp ((struct sockaddr_in *)&from)->sin_port; 2171590Srgrimes break; 218207607Simp } 2191590Srgrimes 220207607Simp /* We should retry if this happens */ 221207607Simp if (n == RP_TIMEOUT) { 222207607Simp printf("Try %d, didn't receive answer from remote.\n", 223207607Simp i + 1); 224207607Simp continue; 225207607Simp } 2261590Srgrimes 227207607Simp /* Otherwise it is a fatal error */ 2281590Srgrimes break; 229207607Simp } 230209550Sgavin if (i == 12) { 231209550Sgavin printf("Transfer timed out.\n"); 232209550Sgavin return; 233209550Sgavin } 234207607Simp if (rp->th_opcode == ERROR) { 235207607Simp tftp_log(LOG_ERR, "Error code %d: %s", rp->th_code, rp->th_msg); 236207607Simp return; 237207607Simp } 2381590Srgrimes 239207607Simp if (write_init(fd, NULL, mode) < 0) { 240207607Simp warn("write_init"); 241207607Simp return; 2421590Srgrimes } 2431590Srgrimes 244207607Simp /* 245207607Simp * If the first packet is an OACK packet instead of an DATA packet, 246207607Simp * handle it different. 247207607Simp */ 248207607Simp if (rp->th_opcode == OACK) { 249207607Simp if (!options_rfc_enabled) { 250207607Simp printf("Got OACK while options are not enabled!\n"); 251207607Simp send_error(peer, EBADOP); 252207607Simp return; 253207607Simp } 2541590Srgrimes 255207607Simp parse_options(peer, rp->th_stuff, n + 2); 2561590Srgrimes 257207607Simp n = send_ack(peer, 0); 258207607Simp if (n > 0) { 259207607Simp printf("Cannot send ACK on OACK.\n"); 260207607Simp return; 261207607Simp } 262207607Simp block = 0; 263207607Simp tftp_receive(peer, &block, &tftp_stats, NULL, 0); 264207607Simp } else { 265207607Simp block = 1; 266207607Simp tftp_receive(peer, &block, &tftp_stats, rp, n); 2671590Srgrimes } 26894443Sume 269207607Simp if (tftp_stats.amount > 0) 270207607Simp printstats("Received", verbose, &tftp_stats); 271207607Simp return; 27294443Sume} 273