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 #if 0 33 #endif 34 35 #include <sys/cdefs.h> 36 /* Many bug fixes are from Jim Guyton <guyton@rand-unix> */ 37 38 /* 39 * TFTP User Program -- Protocol Machines 40 */ 41 #include <sys/socket.h> 42 #include <sys/stat.h> 43 44 #include <netinet/in.h> 45 46 #include <arpa/tftp.h> 47 48 #include <assert.h> 49 #include <err.h> 50 #include <netdb.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <syslog.h> 55 56 #include "tftp.h" 57 #include "tftp-file.h" 58 #include "tftp-utils.h" 59 #include "tftp-io.h" 60 #include "tftp-transfer.h" 61 #include "tftp-options.h" 62 63 /* 64 * Send the requested file. 65 */ 66 int 67 xmitfile(int peer, char *port, int fd, char *name, char *mode) 68 { 69 struct tftphdr *rp; 70 int n, i, ret = 0; 71 uint16_t block; 72 struct sockaddr_storage serv; /* valid server port number */ 73 char recvbuffer[MAXPKTSIZE]; 74 struct tftp_stats tftp_stats; 75 76 stats_init(&tftp_stats); 77 78 memset(&serv, 0, sizeof(serv)); 79 rp = (struct tftphdr *)recvbuffer; 80 81 if (port == NULL) { 82 struct servent *se; 83 se = getservbyname("tftp", "udp"); 84 assert(se != NULL); 85 ((struct sockaddr_in *)&peer_sock)->sin_port = se->s_port; 86 } else 87 ((struct sockaddr_in *)&peer_sock)->sin_port = 88 htons(atoi(port)); 89 90 for (i = 0; i < 12; i++) { 91 struct sockaddr_storage from; 92 93 /* Tell the other side what we want to do */ 94 if (debug & DEBUG_SIMPLE) 95 printf("Sending %s\n", name); 96 97 n = send_wrq(peer, name, mode); 98 if (n > 0) { 99 printf("Cannot send WRQ packet\n"); 100 return -1; 101 } 102 103 /* 104 * The first packet we receive has the new destination port 105 * we have to send the next packets to. 106 */ 107 n = receive_packet(peer, recvbuffer, 108 MAXPKTSIZE, &from, timeoutpacket); 109 110 /* We got some data! */ 111 if (n >= 0) { 112 ((struct sockaddr_in *)&peer_sock)->sin_port = 113 ((struct sockaddr_in *)&from)->sin_port; 114 break; 115 } 116 117 /* This should be retried */ 118 if (n == RP_TIMEOUT) { 119 printf("Try %d, didn't receive answer from remote.\n", 120 i + 1); 121 continue; 122 } 123 124 /* Everything else is fatal */ 125 break; 126 } 127 if (i == 12) { 128 printf("Transfer timed out.\n"); 129 return -1; 130 } 131 if (rp->th_opcode == ERROR) { 132 printf("Got ERROR, aborted\n"); 133 return -1; 134 } 135 136 /* 137 * If the first packet is an OACK instead of an ACK packet, 138 * handle it different. 139 */ 140 if (rp->th_opcode == OACK) { 141 if (!options_rfc_enabled) { 142 printf("Got OACK while options are not enabled!\n"); 143 send_error(peer, EBADOP); 144 return -1; 145 } 146 147 parse_options(peer, rp->th_stuff, n + 2); 148 } 149 150 if (read_init(fd, NULL, mode) < 0) { 151 warn("read_init()"); 152 return -1; 153 } 154 155 block = 1; 156 if (tftp_send(peer, &block, &tftp_stats) != 0) 157 ret = -1; 158 159 read_close(); 160 if (tftp_stats.amount > 0) 161 printstats("Sent", verbose, &tftp_stats); 162 return ret; 163 } 164 165 /* 166 * Receive a file. 167 */ 168 int 169 recvfile(int peer, char *port, int fd, char *name, char *mode) 170 { 171 struct tftphdr *rp; 172 uint16_t block; 173 char recvbuffer[MAXPKTSIZE]; 174 int n, i, ret = 0; 175 struct tftp_stats tftp_stats; 176 177 stats_init(&tftp_stats); 178 179 rp = (struct tftphdr *)recvbuffer; 180 181 if (port == NULL) { 182 struct servent *se; 183 se = getservbyname("tftp", "udp"); 184 assert(se != NULL); 185 ((struct sockaddr_in *)&peer_sock)->sin_port = se->s_port; 186 } else 187 ((struct sockaddr_in *)&peer_sock)->sin_port = 188 htons(atoi(port)); 189 190 for (i = 0; i < 12; i++) { 191 struct sockaddr_storage from; 192 193 /* Tell the other side what we want to do */ 194 if (debug & DEBUG_SIMPLE) 195 printf("Requesting %s\n", name); 196 197 n = send_rrq(peer, name, mode); 198 if (n > 0) { 199 printf("Cannot send RRQ packet\n"); 200 return -1; 201 } 202 203 /* 204 * The first packet we receive has the new destination port 205 * we have to send the next packets to. 206 */ 207 n = receive_packet(peer, recvbuffer, 208 MAXPKTSIZE, &from, timeoutpacket); 209 210 /* We got something useful! */ 211 if (n >= 0) { 212 ((struct sockaddr_in *)&peer_sock)->sin_port = 213 ((struct sockaddr_in *)&from)->sin_port; 214 break; 215 } 216 217 /* We should retry if this happens */ 218 if (n == RP_TIMEOUT) { 219 printf("Try %d, didn't receive answer from remote.\n", 220 i + 1); 221 continue; 222 } 223 224 /* Otherwise it is a fatal error */ 225 break; 226 } 227 if (i == 12) { 228 printf("Transfer timed out.\n"); 229 return -1; 230 } 231 if (rp->th_opcode == ERROR) { 232 tftp_log(LOG_ERR, "Error code %d: %s", rp->th_code, rp->th_msg); 233 return -1; 234 } 235 236 if (write_init(fd, NULL, mode) < 0) { 237 warn("write_init"); 238 return -1; 239 } 240 241 /* 242 * If the first packet is an OACK packet instead of an DATA packet, 243 * handle it different. 244 */ 245 if (rp->th_opcode == OACK) { 246 if (!options_rfc_enabled) { 247 printf("Got OACK while options are not enabled!\n"); 248 send_error(peer, EBADOP); 249 return -1; 250 } 251 252 parse_options(peer, rp->th_stuff, n + 2); 253 254 n = send_ack(peer, 0); 255 if (n > 0) { 256 printf("Cannot send ACK on OACK.\n"); 257 return -1; 258 } 259 block = 0; 260 if (tftp_receive(peer, &block, &tftp_stats, NULL, 0) != 0) 261 ret = -1; 262 } else { 263 block = 1; 264 if (tftp_receive(peer, &block, &tftp_stats, rp, n) != 0) 265 ret = -1; 266 } 267 268 if (tftp_stats.amount > 0) 269 printstats("Received", verbose, &tftp_stats); 270 return ret; 271 } 272