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