1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1983, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 /* Many bug fixes are from Jim Guyton <guyton@rand-unix> */ 34 35 /* 36 * TFTP User Program -- Protocol Machines 37 */ 38 #include <sys/socket.h> 39 #include <sys/stat.h> 40 41 #include <netinet/in.h> 42 43 #include <arpa/tftp.h> 44 45 #include <assert.h> 46 #include <err.h> 47 #include <netdb.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <syslog.h> 52 53 #include "tftp.h" 54 #include "tftp-file.h" 55 #include "tftp-utils.h" 56 #include "tftp-io.h" 57 #include "tftp-transfer.h" 58 #include "tftp-options.h" 59 60 /* 61 * Send the requested file. 62 */ 63 int 64 xmitfile(int peer, char *port, int fd, char *name, char *mode) 65 { 66 struct tftphdr *rp; 67 int n, i, ret = 0; 68 uint16_t block; 69 struct sockaddr_storage serv; /* valid server port number */ 70 char recvbuffer[MAXPKTSIZE]; 71 struct tftp_stats tftp_stats; 72 73 stats_init(&tftp_stats); 74 75 memset(&serv, 0, sizeof(serv)); 76 rp = (struct tftphdr *)recvbuffer; 77 78 if (port == NULL) { 79 struct servent *se; 80 se = getservbyname("tftp", "udp"); 81 assert(se != NULL); 82 ((struct sockaddr_in *)&peer_sock)->sin_port = se->s_port; 83 } else 84 ((struct sockaddr_in *)&peer_sock)->sin_port = 85 htons(atoi(port)); 86 87 for (i = 0; i < 12; i++) { 88 struct sockaddr_storage from; 89 90 /* Tell the other side what we want to do */ 91 if (debug & DEBUG_SIMPLE) 92 printf("Sending %s\n", name); 93 94 n = send_wrq(peer, name, mode); 95 if (n > 0) { 96 printf("Cannot send WRQ packet\n"); 97 return -1; 98 } 99 100 /* 101 * The first packet we receive has the new destination port 102 * we have to send the next packets to. 103 */ 104 n = receive_packet(peer, recvbuffer, 105 MAXPKTSIZE, &from, timeoutpacket); 106 107 /* We got some data! */ 108 if (n >= 0) { 109 ((struct sockaddr_in *)&peer_sock)->sin_port = 110 ((struct sockaddr_in *)&from)->sin_port; 111 break; 112 } 113 114 /* This should be retried */ 115 if (n == RP_TIMEOUT) { 116 printf("Try %d, didn't receive answer from remote.\n", 117 i + 1); 118 continue; 119 } 120 121 /* Everything else is fatal */ 122 break; 123 } 124 if (i == 12) { 125 printf("Transfer timed out.\n"); 126 return -1; 127 } 128 if (rp->th_opcode == ERROR) { 129 printf("Got ERROR, aborted\n"); 130 return -1; 131 } 132 133 /* 134 * If the first packet is an OACK instead of an ACK packet, 135 * handle it different. 136 */ 137 if (rp->th_opcode == OACK) { 138 if (!options_rfc_enabled) { 139 printf("Got OACK while options are not enabled!\n"); 140 send_error(peer, EBADOP); 141 return -1; 142 } 143 144 parse_options(peer, rp->th_stuff, n + 2); 145 } 146 147 if (read_init(fd, NULL, mode) < 0) { 148 warn("read_init()"); 149 return -1; 150 } 151 152 block = 1; 153 if (tftp_send(peer, &block, &tftp_stats) != 0) 154 ret = -1; 155 156 read_close(); 157 if (tftp_stats.amount > 0) 158 printstats("Sent", verbose, &tftp_stats); 159 return ret; 160 } 161 162 /* 163 * Receive a file. 164 */ 165 int 166 recvfile(int peer, char *port, int fd, char *name, char *mode) 167 { 168 struct tftphdr *rp; 169 uint16_t block; 170 char recvbuffer[MAXPKTSIZE]; 171 int n, i, ret = 0; 172 struct tftp_stats tftp_stats; 173 174 stats_init(&tftp_stats); 175 176 rp = (struct tftphdr *)recvbuffer; 177 178 if (port == NULL) { 179 struct servent *se; 180 se = getservbyname("tftp", "udp"); 181 assert(se != NULL); 182 ((struct sockaddr_in *)&peer_sock)->sin_port = se->s_port; 183 } else 184 ((struct sockaddr_in *)&peer_sock)->sin_port = 185 htons(atoi(port)); 186 187 for (i = 0; i < 12; i++) { 188 struct sockaddr_storage from; 189 190 /* Tell the other side what we want to do */ 191 if (debug & DEBUG_SIMPLE) 192 printf("Requesting %s\n", name); 193 194 n = send_rrq(peer, name, mode); 195 if (n > 0) { 196 printf("Cannot send RRQ packet\n"); 197 return -1; 198 } 199 200 /* 201 * The first packet we receive has the new destination port 202 * we have to send the next packets to. 203 */ 204 n = receive_packet(peer, recvbuffer, 205 MAXPKTSIZE, &from, timeoutpacket); 206 207 /* We got something useful! */ 208 if (n >= 0) { 209 ((struct sockaddr_in *)&peer_sock)->sin_port = 210 ((struct sockaddr_in *)&from)->sin_port; 211 break; 212 } 213 214 /* We should retry if this happens */ 215 if (n == RP_TIMEOUT) { 216 printf("Try %d, didn't receive answer from remote.\n", 217 i + 1); 218 continue; 219 } 220 221 /* Otherwise it is a fatal error */ 222 break; 223 } 224 if (i == 12) { 225 printf("Transfer timed out.\n"); 226 return -1; 227 } 228 if (rp->th_opcode == ERROR) { 229 tftp_log(LOG_ERR, "Error code %d: %s", rp->th_code, rp->th_msg); 230 return -1; 231 } 232 233 if (write_init(fd, NULL, mode) < 0) { 234 warn("write_init"); 235 return -1; 236 } 237 238 /* 239 * If the first packet is an OACK packet instead of an DATA packet, 240 * handle it different. 241 */ 242 if (rp->th_opcode == OACK) { 243 if (!options_rfc_enabled) { 244 printf("Got OACK while options are not enabled!\n"); 245 send_error(peer, EBADOP); 246 return -1; 247 } 248 249 parse_options(peer, rp->th_stuff, n + 2); 250 251 n = send_ack(peer, 0); 252 if (n > 0) { 253 printf("Cannot send ACK on OACK.\n"); 254 return -1; 255 } 256 block = 0; 257 if (tftp_receive(peer, &block, &tftp_stats, NULL, 0) != 0) 258 ret = -1; 259 } else { 260 block = 1; 261 if (tftp_receive(peer, &block, &tftp_stats, rp, n) != 0) 262 ret = -1; 263 } 264 265 if (tftp_stats.amount > 0) 266 printstats("Received", verbose, &tftp_stats); 267 return ret; 268 } 269